Added Junits
[portal.git] / ecomp-portal-BE-common / src / main / java / org / onap / portalapp / portal / service / ApplicationsRestClientServiceImpl.java
1 /*-
2  * ============LICENSE_START==========================================
3  * ONAP Portal
4  * ===================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  *
8  * Unless otherwise specified, all software contained herein is licensed
9  * under the Apache License, Version 2.0 (the "License");
10  * you may not use this software except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *             http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Unless otherwise specified, all documentation contained herein is licensed
22  * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23  * you may not use this documentation except in compliance with the License.
24  * You may obtain a copy of the License at
25  *
26  *             https://creativecommons.org/licenses/by/4.0/
27  *
28  * Unless required by applicable law or agreed to in writing, documentation
29  * distributed under the License is distributed on an "AS IS" BASIS,
30  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31  * See the License for the specific language governing permissions and
32  * limitations under the License.
33  *
34  * ============LICENSE_END============================================
35  *
36  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
37  */
38 package org.onap.portalapp.portal.service;
39
40 import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
41
42 import java.lang.reflect.Type;
43 import java.net.MalformedURLException;
44 import java.net.URL;
45 import java.util.Base64;
46 import java.util.Date;
47
48 import javax.annotation.PostConstruct;
49 import javax.servlet.http.HttpServletResponse;
50 import javax.ws.rs.core.MediaType;
51 import javax.ws.rs.core.Response;
52
53 import org.apache.commons.lang.StringUtils;
54 import org.apache.cxf.jaxrs.client.WebClient;
55 import org.apache.cxf.transport.http.HTTPException;
56 import org.onap.portalapp.portal.domain.EPApp;
57 import org.onap.portalapp.portal.logging.aop.EPAuditLog;
58 import org.onap.portalapp.portal.logging.aop.EPMetricsLog;
59 import org.onap.portalapp.portal.logging.format.EPAppMessagesEnum;
60 import org.onap.portalapp.portal.logging.logic.EPLogUtil;
61 import org.onap.portalapp.portal.utils.EPCommonSystemProperties;
62 import org.onap.portalapp.portal.utils.EcompPortalUtils;
63 import org.onap.portalapp.util.SystemType;
64 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
65 import org.onap.portalsdk.core.onboarding.util.CipherUtil;
66 import org.onap.portalsdk.core.util.SystemProperties;
67 import org.slf4j.MDC;
68 import org.springframework.beans.factory.annotation.Autowired;
69 import org.springframework.context.annotation.EnableAspectJAutoProxy;
70 import org.springframework.stereotype.Service;
71
72 import com.fasterxml.jackson.databind.ObjectMapper;
73 import com.google.gson.Gson;
74 import com.google.gson.GsonBuilder;
75 import com.google.gson.JsonDeserializationContext;
76 import com.google.gson.JsonDeserializer;
77 import com.google.gson.JsonElement;
78 import com.google.gson.JsonParseException;
79
80 @Service("applicationsRestClientService")
81 @org.springframework.context.annotation.Configuration
82 @EnableAspectJAutoProxy
83 @EPAuditLog
84 public class ApplicationsRestClientServiceImpl implements ApplicationsRestClientService {
85
86         private static final String PASSWORD_HEADER = "password";
87
88         private static final String APP_USERNAME_HEADER = "username";
89
90         private static final String BASIC_AUTHENTICATION_HEADER = "Authorization";
91
92         private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ApplicationsRestClientServiceImpl.class);
93
94         @Autowired
95         private AppsCacheService appsCacheService;
96
97         Gson gson = null;
98
99         private final ObjectMapper mapper = new ObjectMapper();
100
101         @PostConstruct
102         private void init() {
103                 logger.debug(EELFLoggerDelegate.debugLogger, "initializing");
104                 GsonBuilder builder = new GsonBuilder();
105
106                 // Register an adapter to manage the date types as long values
107                 builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
108                         public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
109                                         throws JsonParseException {
110                                 return new Date(json.getAsJsonPrimitive().getAsLong());
111                         }
112                 });
113
114                 gson = builder.create();
115         }
116
117         // TODO: do we need to do additional logging for remote API calls?
118         private static WebClient createClientForPath(String baseUri, String path) {
119                 logger.info(EELFLoggerDelegate.debugLogger, "Creating web client for " + baseUri + "   +   " + path);
120                 WebClient client = WebClient.create(baseUri);
121                 client.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
122                 client.path(path);
123                 return client;
124         }
125
126         @EPMetricsLog
127         private void verifyResponse(Response response) throws HTTPException {
128                 int status = response.getStatus();
129                 logger.debug(EELFLoggerDelegate.debugLogger, "http response status=" + status);
130                 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE, Integer.toString(status));
131                 if (!isHttpSuccess(status)) {
132                         String errMsg = "Failed. Status=" + status + "; [" + response.getStatusInfo().getReasonPhrase().toString()
133                                         + "]";
134                         URL url = null;
135                         try {
136                                 // must not be null to avoid NPE in HTTPException constructor
137                                 url = new URL("http://null");
138                                 if (response.getLocation() != null)
139                                         url = response.getLocation().toURL();
140                         } catch (MalformedURLException e) {
141                                 // never mind. it is only for the debug message.
142                                 logger.warn(EELFLoggerDelegate.errorLogger, "Failed to build URL", e);
143                         }
144                         logger.error(EELFLoggerDelegate.errorLogger, "http response failed. " + errMsg + "; url=" + url);
145                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeIncorrectHttpStatusError);
146                         throw new HTTPException(status, errMsg, url);
147                 }
148         }
149
150         private static boolean isHttpSuccess(int status) {
151                 return status / 100 == 2;
152         }
153         
154         
155         private WebClient createClientForApp(long appId, String restPath) {
156                 return createClientFor(appId, restPath, SystemType.APPLICATION);
157         }
158
159         //TODO Need to implement the mylogins once the endpoint is confirmed
160         @EPMetricsLog
161         private WebClient createClientFor(long appSystemId, String restPath, SystemType type) {
162                 logger.debug(EELFLoggerDelegate.debugLogger, "creating client for appId=" + appSystemId + "; restPath=" + restPath);
163                 EPApp externalApp = null;
164                 
165                 if(type == SystemType.APPLICATION){
166                 externalApp = appsCacheService.getApp(appSystemId);
167                 }else{
168                         // TO DO 
169                 }
170                 
171                 if (externalApp != null) {
172                         String appBaseUri = (type == SystemType.APPLICATION) ? externalApp.getAppRestEndpoint() : "";
173                         String username = (type == SystemType.APPLICATION) ? externalApp.getUsername(): "";
174                         String encriptedPwd = (type == SystemType.APPLICATION) ? externalApp.getAppPassword(): "";
175                         String appName = (type == SystemType.APPLICATION) ? externalApp.getName(): "";
176                         String decreptedAppPwd = StringUtils.EMPTY;
177
178                         // Set local context
179                         MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTP);
180                         if (appBaseUri != null && appBaseUri.contains("https")) {
181                                 MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTPS);
182                         }
183                         MDC.put(EPCommonSystemProperties.FULL_URL, appBaseUri + restPath);
184                         MDC.put(EPCommonSystemProperties.TARGET_ENTITY, appName);
185                         MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, restPath);
186
187                         try {
188                                 decreptedAppPwd = CipherUtil.decryptPKC(encriptedPwd,
189                                                 SystemProperties.getProperty(SystemProperties.Decryption_Key));
190                         } catch (Exception e) {
191                                 logger.error(EELFLoggerDelegate.errorLogger, "createClientFor failed to decrypt", e);
192                         }
193                         
194                         WebClient client = createClientForPath(appBaseUri, restPath);
195
196                         // support basic authentication for some partners
197                         String encoding = Base64.getEncoder().encodeToString((username + ":" + decreptedAppPwd).getBytes());
198                         String encodingStr = "Basic " + encoding;
199                         client.header(BASIC_AUTHENTICATION_HEADER, encodingStr);
200
201                         // But still keep code downward compatible for non compliant apps
202                         client.header(APP_USERNAME_HEADER, username);
203                         client.header(PASSWORD_HEADER, decreptedAppPwd);
204
205                         client.header(SystemProperties.ECOMP_REQUEST_ID, MDC.get(MDC_KEY_REQUEST_ID));
206                         client.header(SystemProperties.USERAGENT_NAME, EPCommonSystemProperties.ECOMP_PORTAL_BE);
207                         
208                         logger.debug(EELFLoggerDelegate.debugLogger,
209                                         String.format("App %d found, baseUri=[%s], Headers: [%s=%s, %s=%s, %s=%s]", appSystemId, appBaseUri,
210                                                         APP_USERNAME_HEADER, username, PASSWORD_HEADER, encriptedPwd, BASIC_AUTHENTICATION_HEADER, encodingStr));
211
212                         return client;
213                 }
214                 return null;
215         }
216
217         @Override
218         public <T> T get(Class<T> clazz, long appId, String restPath) throws HTTPException {
219                 T t = null;
220                 Response response = getResponse(appId, restPath);
221
222                 if (response != null) {
223                         verifyResponse(response);
224                         String str = response.readEntity(String.class);
225                         EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
226                         try {
227                                 t = gson.fromJson(str, clazz);
228                         } catch (Exception e) {
229                                 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
230                         }
231                 }
232
233                 return t;
234         }
235         
236         @Override
237         public String getIncomingJsonString(long appId, String restPath) throws HTTPException {
238                 Response response = getResponse(appId, restPath);
239
240                 if (response != null) {
241                         verifyResponse(response);
242                         String incomingJson = response.readEntity(String.class);
243                         return incomingJson;
244                 }
245                 
246                 return "";
247         }
248
249
250         /*
251          * (non-Javadoc)
252          * 
253          * @see
254          * org.onap.portalapp.portal.service.ApplicationsRestClientService#get(
255          * java.lang.Class, long, java.lang.String, boolean)
256          */
257         @Override
258         public <T> T get(Class<T> clazz, long appId, String restPath, boolean useJacksonMapper) throws HTTPException {
259
260                 if (!useJacksonMapper)
261                         return get(clazz, appId, restPath);
262
263                 T t = null;
264                 Response response = getResponse(appId, restPath);
265
266                 if (response != null) {
267                         verifyResponse(response);
268                         String str = response.readEntity(String.class);
269                         EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
270
271                         try {
272                                 t = mapper.readValue(str, clazz);
273                         } catch (Exception e) {
274                                 e.printStackTrace();
275                                 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
276                         }
277                 }
278
279                 return t;
280         }
281
282         protected Response getResponse(long appId, String restPath) {
283                 WebClient webClient = null;
284                 Response response = null;
285
286                 webClient = createClientForApp(appId, restPath);
287                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET request =", "no-payload");
288
289                 try {
290                         if (webClient != null) {
291                                 response = webClient.get();
292                         } else {
293                                 logger.error(EELFLoggerDelegate.errorLogger,
294                                                 "Unable to create the Webclient to make the '" + restPath + "' API call.");
295                         }
296                 } catch (Exception e) {
297                         MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
298                                         Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
299                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
300                         logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the GET REST API call", e);
301                 }
302                 return response;
303         }
304         
305         
306         @Override
307         public <T> T post(Class<T> clazz, long appId, Object payload, String restPath, SystemType type) throws HTTPException {
308                 WebClient client = null;
309                 Response response = null;
310                 T t = null;
311
312                 client = createClientFor(appId, restPath, type);
313                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST request =", payload);
314
315                 try {
316                         if (client != null) {
317                                 response = client.post(payload);
318                         } else {
319                                 logger.error(EELFLoggerDelegate.errorLogger,
320                                                 "Unable to create the Webclient to make the '" + restPath + "' API call.");
321                         }
322                 } catch (Exception e) {
323                         MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
324                                         Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
325                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
326                         logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the POST REST API call", e);
327                 }
328
329                 if (response != null) {
330                         verifyResponse(response);
331
332                         // String contentType = response.getHeaderString("Content-Type");
333                         if (clazz != null) {
334                                 String str = response.readEntity(String.class);
335                                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
336                                 try {
337                                         t = gson.fromJson(str, clazz);
338                                 } catch (Exception e) {
339                                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
340                                 }
341                         }
342                 }
343                 return t;
344         }
345
346         @Override
347         public <T> T post(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
348                 return post( clazz, appId, payload, restPath, SystemType.APPLICATION);
349         }
350
351         //@Override
352         public <T> T postForClass(Class<T> clazz, long appId, Object payload, String restPath, Class<T> forClass) throws HTTPException {
353                 WebClient client = null;
354                 Response response = null;
355                 T t = null;
356                 logger.debug(EELFLoggerDelegate.debugLogger, "Entering to createClientForApp method for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
357                 client = createClientForApp(appId, restPath);
358                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST request =", payload);
359                 logger.debug(EELFLoggerDelegate.debugLogger, "Finished createClientForApp method for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
360                 try {
361                         if (client != null) {
362                                 logger.debug(EELFLoggerDelegate.debugLogger, "Entering to POST for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
363                                 response = client.post(payload);
364                                 logger.debug(EELFLoggerDelegate.debugLogger, "Finished to POST for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
365                         } else {
366                                 logger.error(EELFLoggerDelegate.errorLogger,
367                                                 "Unable to create the Webclient to make the '" + restPath + "' API call.");
368                         }
369                 } catch (Exception e) {
370                         MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
371                                         Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
372                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
373                         logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the POST REST API call", e);
374                 }
375
376                 if (response != null) {
377                         verifyResponse(response);
378
379                         // String contentType = response.getHeaderString("Content-Type");
380                         if (clazz != null) {
381                                 String str = response.readEntity(String.class);
382                                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
383                                 try {
384                                         t = gson.fromJson(str, clazz);
385                                 } catch (Exception e) {
386                                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
387                                 }
388                         }
389                 }
390                 return t;
391         }
392
393         
394         @Override
395         public <T> T put(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
396                 WebClient client = null;
397                 Response response = null;
398                 T t = null;
399
400                 logger.debug(EELFLoggerDelegate.debugLogger, "Entering to createClientForApp method for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
401
402                 client = createClientForApp(appId, restPath);
403                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT request =", payload);
404                 
405                 logger.debug(EELFLoggerDelegate.debugLogger, "Finished createClientForApp method for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
406
407                 try {
408                         if (client != null) {
409                                 logger.debug(EELFLoggerDelegate.debugLogger, "Entering to PUT for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
410
411                                 response = client.put(payload);
412                                 
413                                 logger.debug(EELFLoggerDelegate.debugLogger, "Finished to PUT for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
414
415                         } else {
416                                 logger.error(EELFLoggerDelegate.errorLogger,
417                                                 "Unable to create the Webclient to make the '" + restPath + "' API call.");
418                         }
419                 } catch (Exception e) {
420                         MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
421                                         Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
422                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
423                         logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the PUT REST API call", e);
424                 }
425
426                 if (response != null) {
427                         verifyResponse(response);
428                         String str = response.readEntity(String.class);
429                         EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT result =", str);
430                         try {
431                                 t = gson.fromJson(str, clazz);
432                         } catch (Exception e) {
433                                 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
434                         }
435                 }
436                 return t;
437         }
438 }