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