2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ===================================================================
7 * Modifications Copyright (c) 2019 Samsung
8 * ===================================================================
10 * Unless otherwise specified, all software contained herein is licensed
11 * under the Apache License, Version 2.0 (the "License");
12 * you may not use this software except in compliance with the License.
13 * You may obtain a copy of the License at
15 * http://www.apache.org/licenses/LICENSE-2.0
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
23 * Unless otherwise specified, all documentation contained herein is licensed
24 * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
25 * you may not use this documentation except in compliance with the License.
26 * You may obtain a copy of the License at
28 * https://creativecommons.org/licenses/by/4.0/
30 * Unless required by applicable law or agreed to in writing, documentation
31 * distributed under the License is distributed on an "AS IS" BASIS,
32 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33 * See the License for the specific language governing permissions and
34 * limitations under the License.
36 * ============LICENSE_END============================================
40 package org.onap.portalapp.portal.service;
42 import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
44 import java.lang.reflect.Type;
45 import java.net.MalformedURLException;
47 import java.util.Base64;
48 import java.util.Date;
50 import javax.annotation.PostConstruct;
51 import javax.servlet.http.HttpServletResponse;
52 import javax.ws.rs.core.MediaType;
53 import javax.ws.rs.core.Response;
55 import org.apache.commons.lang.StringUtils;
56 import org.apache.cxf.jaxrs.client.WebClient;
57 import org.apache.cxf.jaxrs.impl.ResponseImpl;
58 import org.apache.cxf.transport.http.HTTPException;
59 import org.onap.portalapp.portal.domain.EPApp;
60 import org.onap.portalapp.portal.logging.aop.EPAuditLog;
61 import org.onap.portalapp.portal.logging.aop.EPMetricsLog;
62 import org.onap.portalapp.portal.logging.format.EPAppMessagesEnum;
63 import org.onap.portalapp.portal.logging.logic.EPLogUtil;
64 import org.onap.portalapp.portal.utils.EPCommonSystemProperties;
65 import org.onap.portalapp.portal.utils.EcompPortalUtils;
66 import org.onap.portalapp.util.SystemType;
67 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
68 import org.onap.portalsdk.core.onboarding.exception.CipherUtilException;
69 import org.onap.portalsdk.core.onboarding.util.CipherUtil;
70 import org.onap.portalsdk.core.util.SystemProperties;
72 import org.springframework.beans.factory.annotation.Autowired;
73 import org.springframework.context.annotation.EnableAspectJAutoProxy;
74 import org.springframework.stereotype.Service;
76 import com.fasterxml.jackson.databind.ObjectMapper;
77 import com.google.gson.Gson;
78 import com.google.gson.GsonBuilder;
79 import com.google.gson.JsonDeserializationContext;
80 import com.google.gson.JsonDeserializer;
81 import com.google.gson.JsonElement;
82 import com.google.gson.JsonParseException;
84 @Service("applicationsRestClientService")
85 @org.springframework.context.annotation.Configuration
86 @EnableAspectJAutoProxy
88 public class ApplicationsRestClientServiceImpl implements ApplicationsRestClientService {
90 private static final String PASSWORD_HEADER = "password";
92 private static final String APP_USERNAME_HEADER = "username";
94 private static final String BASIC_AUTHENTICATION_HEADER = "Authorization";
96 private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ApplicationsRestClientServiceImpl.class);
99 private AppsCacheService appsCacheService;
103 private final ObjectMapper mapper = new ObjectMapper();
106 private void init() {
107 logger.debug(EELFLoggerDelegate.debugLogger, "initializing");
108 GsonBuilder builder = new GsonBuilder();
110 // Register an adapter to manage the date types as long values
111 builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
112 public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
113 throws JsonParseException {
114 return new Date(json.getAsJsonPrimitive().getAsLong());
118 gson = builder.create();
121 // TODO: do we need to do additional logging for remote API calls?
122 private static WebClient createClientForPath(String baseUri, String path) {
123 logger.info(EELFLoggerDelegate.debugLogger, "Creating web client for " + baseUri + " + " + path);
124 WebClient client = WebClient.create(baseUri);
125 client.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
131 private void verifyResponse(Response response,String restPath) throws HTTPException {
132 int status = response.getStatus();
133 logger.debug(EELFLoggerDelegate.debugLogger, "http response status=" + status);
134 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE, Integer.toString(status));
135 if (!isHttpSuccess(status)) {
136 String errMsg = "Failed. Status=" + status + restPath +"; [" + ((ResponseImpl)response).getStatusInfo().getReasonPhrase().toString()
140 // must not be null to avoid NPE in HTTPException constructor
141 url = new URL("http://null");
142 if (((ResponseImpl)response).getLocation() != null)
143 url = ((ResponseImpl)response).getLocation().toURL();
144 } catch (MalformedURLException e) {
145 // never mind. it is only for the debug message.
146 logger.warn(EELFLoggerDelegate.errorLogger, "Failed to build URL", e);
148 logger.error(EELFLoggerDelegate.errorLogger, "http response failed. " + restPath + errMsg + "; url=" + url);
149 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeIncorrectHttpStatusError);
150 throw new HTTPException(status, errMsg, url);
154 private static boolean isHttpSuccess(int status) {
155 return status / 100 == 2;
159 private WebClient createClientForApp(long appId, String restPath) {
160 return createClientFor(appId, restPath, SystemType.APPLICATION);
165 //TODO Need to implement the mylogins once the endpoint is confirmed
167 private WebClient createClientFor(long appSystemId, String restPath, SystemType type) {
168 logger.debug(EELFLoggerDelegate.debugLogger, "creating client for appId=" + appSystemId + "; restPath=" + restPath);
169 EPApp externalApp = null;
171 if(type == SystemType.APPLICATION){
172 externalApp = appsCacheService.getApp(appSystemId);
177 if (externalApp != null) {
178 String appBaseUri = (type == SystemType.APPLICATION) ? externalApp.getAppRestEndpoint() : "";
179 String username = (type == SystemType.APPLICATION) ? externalApp.getUsername(): "";
180 String encriptedPwd = (type == SystemType.APPLICATION) ? externalApp.getAppPassword(): "";
182 String appName = (type == SystemType.APPLICATION) ? externalApp.getName(): "";
183 String decreptedAppPwd = StringUtils.EMPTY;
186 MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTP);
187 if (appBaseUri != null && appBaseUri.contains("https")) {
188 MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTPS);
190 MDC.put(EPCommonSystemProperties.FULL_URL, appBaseUri + restPath);
191 MDC.put(EPCommonSystemProperties.TARGET_ENTITY, appName);
192 MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, restPath);
194 if(!encriptedPwd.isEmpty() || encriptedPwd != null || StringUtils.isEmpty(encriptedPwd)){
196 decreptedAppPwd = CipherUtil.decryptPKC(encriptedPwd,
197 SystemProperties.getProperty(SystemProperties.Decryption_Key));
198 } catch (Exception e) {
199 logger.error(EELFLoggerDelegate.errorLogger, "createClientFor failed to decrypt", e);
202 WebClient client = createClientForPath(appBaseUri, restPath);
205 if(externalApp.getAppPassword().isEmpty() || externalApp.getAppPassword()==null){
206 logger.debug(EELFLoggerDelegate.debugLogger, "Entering in the externalApp get app password contains null : {}");
208 externalApp = appsCacheService.getApp(1L);
209 logger.debug(EELFLoggerDelegate.debugLogger, "external App Information : {}",externalApp);
211 String mechidUsername=externalApp.getUsername();
212 logger.debug(EELFLoggerDelegate.debugLogger, "external App mechidUsername Information : {}",mechidUsername);
214 String password=externalApp.getAppPassword();
215 String decreptedexternalAppPwd = StringUtils.EMPTY;
217 decreptedexternalAppPwd = CipherUtil.decryptPKC(password,
218 SystemProperties.getProperty(SystemProperties.Decryption_Key));
219 } catch (CipherUtilException e) {
220 logger.error(EELFLoggerDelegate.errorLogger, "failed to decreptedexternalAppPwd when external app pwd is null", e);
223 username =mechidUsername;
224 decreptedAppPwd = decreptedexternalAppPwd;
227 logger.debug(EELFLoggerDelegate.debugLogger, "Entering in the externalApp get app password is not null : {}" );
229 // support basic authentication for some partners
230 String encoding = Base64.getEncoder().encodeToString((username + ":" + decreptedAppPwd).getBytes());
231 String encodingStr = "Basic " + encoding;
232 client.header(BASIC_AUTHENTICATION_HEADER, encodingStr);
235 // But still keep code downward compatible for non compliant apps
236 client.header(APP_USERNAME_HEADER, username);
237 client.header(PASSWORD_HEADER, decreptedAppPwd);
239 String encoding = Base64.getEncoder().encodeToString((username + ":" + decreptedAppPwd).getBytes());
240 String encodingStr = "Basic " + encoding;
241 client.header(BASIC_AUTHENTICATION_HEADER, encodingStr);
242 client.header(SystemProperties.ECOMP_REQUEST_ID, MDC.get(MDC_KEY_REQUEST_ID));
243 client.header(SystemProperties.USERAGENT_NAME, EPCommonSystemProperties.ECOMP_PORTAL_BE);
244 logger.debug(EELFLoggerDelegate.debugLogger,
245 String.format("check the partner application URL App %d found, baseUri=[%s], Headers: [%s=%s]", appSystemId, appBaseUri,
246 APP_USERNAME_HEADER, username));
253 public <T> T get(Class<T> clazz, long appId, String restPath) throws HTTPException {
255 Response response = getResponse(appId, restPath);
257 if (response != null) {
258 //verifyResponse(response);
259 verifyResponse(response,restPath);
260 /* It is not recommendable to use the implementation class org.apache.cxf.jaxrs.impl.ResponseImpl in the code,
261 but had to force this in-order to prevent conflict with the ResponseImpl class of Jersey Client which
262 doesn't work as expected. Created Portal-253 for tracking */
263 String str = ((ResponseImpl)response).readEntity(String.class);
265 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
267 t = gson.fromJson(str, clazz);
268 } catch (Exception e) {
269 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
277 public String getIncomingJsonString(long appId, String restPath) throws HTTPException {
278 Response response = getResponse(appId, restPath);
280 if (response != null) {
281 //verifyResponse(response);
282 verifyResponse(response,restPath);
283 /* It is not recommendable to use the implementation class org.apache.cxf.jaxrs.impl.ResponseImpl in the code,
284 but had to force this in-order to prevent conflict with the ResponseImpl class of Jersey Client which
285 doesn't work as expected. Created Portal-253 for tracking */
286 String incomingJson = ((ResponseImpl)response).readEntity(String.class);
298 * org.onap.portalapp.portal.service.ApplicationsRestClientService#get(
299 * java.lang.Class, long, java.lang.String, boolean)
302 public <T> T get(Class<T> clazz, long appId, String restPath, boolean useJacksonMapper) throws HTTPException {
304 if (!useJacksonMapper)
305 return get(clazz, appId, restPath);
308 Response response = getResponse(appId, restPath);
310 if (response != null) {
311 //verifyResponse(response);
312 verifyResponse(response,restPath);
313 String str = ((ResponseImpl)response).readEntity(String.class);
314 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
317 t = mapper.readValue(str, clazz);
318 } catch (Exception e) {
320 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
327 protected Response getResponse(long appId, String restPath) {
328 WebClient webClient = null;
329 Response response = null;
331 webClient = createClientForApp(appId, restPath);
332 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET request =", "no-payload");
335 if (webClient != null) {
336 response = webClient.get();
338 logger.error(EELFLoggerDelegate.errorLogger,
339 "Unable to create the Webclient to make the '" + restPath + "' API call.");
341 } catch (Exception e) {
342 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
343 Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
344 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
345 logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the GET REST API call", e);
351 @SuppressWarnings({ "unchecked", "null" })
353 public <T> T post(Class<T> clazz, long appId, Object payload, String restPath, SystemType type) throws HTTPException {
354 WebClient client = null;
355 Response response = null;
358 client = createClientFor(appId, restPath, type);
359 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST request =", payload);
362 if (client != null) {
363 response = client.post(payload);
365 logger.error(EELFLoggerDelegate.errorLogger,
366 "Unable to create the Webclient to make the '" + restPath + "' API call.");
368 } catch (Exception e) {
369 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
370 Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
371 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
372 logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the POST REST API call", e);
375 if (response != null) {
376 //verifyResponse(response);
377 verifyResponse(response,restPath);
378 // String contentType = response.getHeaderString("Content-Type");
380 String str = ((ResponseImpl)response).readEntity(String.class);
381 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
383 t = (T) gson.fromJson(str, clazz);
385 //t = gson.fromJson(str, clazz);
386 } catch (Exception e) {
387 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
395 public <T> T post(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
396 return post( clazz, appId, payload, restPath, SystemType.APPLICATION);
401 public <T> T put(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
402 WebClient client = null;
403 Response response = null;
406 logger.debug(EELFLoggerDelegate.debugLogger, "Entering to createClientForApp method for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
408 client = createClientForApp(appId, restPath);
409 EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT request =", payload);
411 logger.debug(EELFLoggerDelegate.debugLogger, "Finished createClientForApp method for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
414 if (client != null) {
415 logger.debug(EELFLoggerDelegate.debugLogger, "Entering to PUT for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
417 response = client.put(payload);
419 logger.debug(EELFLoggerDelegate.debugLogger, "Finished to PUT for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
422 logger.error(EELFLoggerDelegate.errorLogger,
423 "Unable to create the Webclient to make the '" + restPath + "' API call.");
425 } catch (Exception e) {
426 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
427 Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
428 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
429 logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the PUT REST API call", e);
432 if (response != null) {
433 //verifyResponse(response);
434 verifyResponse(response,restPath);
435 String str = ((ResponseImpl)response).readEntity(String.class);
436 EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT result =", str);
438 t = gson.fromJson(str, clazz);
439 } catch (Exception e) {
440 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);