2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ===================================================================
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
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
26 * https://creativecommons.org/licenses/by/4.0/
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.
34 * ============LICENSE_END============================================
36 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
38 package org.onap.portalapp.portal.service;
40 import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
42 import java.lang.reflect.Type;
43 import java.net.MalformedURLException;
45 import java.util.Base64;
46 import java.util.Date;
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;
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;
68 import org.springframework.beans.factory.annotation.Autowired;
69 import org.springframework.context.annotation.EnableAspectJAutoProxy;
70 import org.springframework.stereotype.Service;
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;
80 @Service("applicationsRestClientService")
81 @org.springframework.context.annotation.Configuration
82 @EnableAspectJAutoProxy
84 public class ApplicationsRestClientServiceImpl implements ApplicationsRestClientService {
86 private static final String PASSWORD_HEADER = "password";
88 private static final String APP_USERNAME_HEADER = "username";
90 private static final String BASIC_AUTHENTICATION_HEADER = "Authorization";
92 private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ApplicationsRestClientServiceImpl.class);
95 private AppsCacheService appsCacheService;
99 private final ObjectMapper mapper = new ObjectMapper();
102 private void init() {
103 logger.debug(EELFLoggerDelegate.debugLogger, "initializing");
104 GsonBuilder builder = new GsonBuilder();
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());
114 gson = builder.create();
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);
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()
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);
144 logger.error(EELFLoggerDelegate.errorLogger, "http response failed. " + errMsg + "; url=" + url);
145 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeIncorrectHttpStatusError);
146 throw new HTTPException(status, errMsg, url);
150 private static boolean isHttpSuccess(int status) {
151 return status / 100 == 2;
155 private WebClient createClientForApp(long appId, String restPath) {
156 return createClientFor(appId, restPath, SystemType.APPLICATION);
159 //TODO Need to implement the mylogins once the endpoint is confirmed
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;
165 if(type == SystemType.APPLICATION){
166 externalApp = appsCacheService.getApp(appSystemId);
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;
179 MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTP);
180 if (appBaseUri != null && appBaseUri.contains("https")) {
181 MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTPS);
183 MDC.put(EPCommonSystemProperties.FULL_URL, appBaseUri + restPath);
184 MDC.put(EPCommonSystemProperties.TARGET_ENTITY, appName);
185 MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, restPath);
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);
194 WebClient client = createClientForPath(appBaseUri, restPath);
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);
201 // But still keep code downward compatible for non compliant apps
202 client.header(APP_USERNAME_HEADER, username);
203 client.header(PASSWORD_HEADER, decreptedAppPwd);
205 client.header(SystemProperties.ECOMP_REQUEST_ID, MDC.get(MDC_KEY_REQUEST_ID));
206 client.header(SystemProperties.USERAGENT_NAME, EPCommonSystemProperties.ECOMP_PORTAL_BE);
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));
218 public <T> T get(Class<T> clazz, long appId, String restPath) throws HTTPException {
220 Response response = getResponse(appId, restPath);
222 if (response != null) {
223 verifyResponse(response);
224 String str = response.readEntity(String.class);
225 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
227 t = gson.fromJson(str, clazz);
228 } catch (Exception e) {
229 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
237 public String getIncomingJsonString(long appId, String restPath) throws HTTPException {
238 Response response = getResponse(appId, restPath);
240 if (response != null) {
241 verifyResponse(response);
242 String incomingJson = response.readEntity(String.class);
254 * org.onap.portalapp.portal.service.ApplicationsRestClientService#get(
255 * java.lang.Class, long, java.lang.String, boolean)
258 public <T> T get(Class<T> clazz, long appId, String restPath, boolean useJacksonMapper) throws HTTPException {
260 if (!useJacksonMapper)
261 return get(clazz, appId, restPath);
264 Response response = getResponse(appId, restPath);
266 if (response != null) {
267 verifyResponse(response);
268 String str = response.readEntity(String.class);
269 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
272 t = mapper.readValue(str, clazz);
273 } catch (Exception e) {
275 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
282 protected Response getResponse(long appId, String restPath) {
283 WebClient webClient = null;
284 Response response = null;
286 webClient = createClientForApp(appId, restPath);
287 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET request =", "no-payload");
290 if (webClient != null) {
291 response = webClient.get();
293 logger.error(EELFLoggerDelegate.errorLogger,
294 "Unable to create the Webclient to make the '" + restPath + "' API call.");
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);
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;
312 client = createClientFor(appId, restPath, type);
313 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST request =", payload);
316 if (client != null) {
317 response = client.post(payload);
319 logger.error(EELFLoggerDelegate.errorLogger,
320 "Unable to create the Webclient to make the '" + restPath + "' API call.");
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);
329 if (response != null) {
330 verifyResponse(response);
332 // String contentType = response.getHeaderString("Content-Type");
334 String str = response.readEntity(String.class);
335 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
337 t = gson.fromJson(str, clazz);
338 } catch (Exception e) {
339 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
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);
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;
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);
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);
366 logger.error(EELFLoggerDelegate.errorLogger,
367 "Unable to create the Webclient to make the '" + restPath + "' API call.");
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);
376 if (response != null) {
377 verifyResponse(response);
379 // String contentType = response.getHeaderString("Content-Type");
381 String str = response.readEntity(String.class);
382 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
384 t = gson.fromJson(str, clazz);
385 } catch (Exception e) {
386 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
395 public <T> T put(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
396 WebClient client = null;
397 Response response = null;
400 logger.debug(EELFLoggerDelegate.debugLogger, "Entering to createClientForApp method for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
402 client = createClientForApp(appId, restPath);
403 EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT request =", payload);
405 logger.debug(EELFLoggerDelegate.debugLogger, "Finished createClientForApp method for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
408 if (client != null) {
409 logger.debug(EELFLoggerDelegate.debugLogger, "Entering to PUT for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
411 response = client.put(payload);
413 logger.debug(EELFLoggerDelegate.debugLogger, "Finished to PUT for payload: {} and restPath: {} and appId: {}", payload.toString(), restPath, appId);
416 logger.error(EELFLoggerDelegate.errorLogger,
417 "Unable to create the Webclient to make the '" + restPath + "' API call.");
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);
426 if (response != null) {
427 verifyResponse(response);
428 String str = response.readEntity(String.class);
429 EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT result =", str);
431 t = gson.fromJson(str, clazz);
432 } catch (Exception e) {
433 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);