2 * ================================================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ================================================================================
20 package org.openecomp.portalapp.portal.service;
22 import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
24 import java.lang.reflect.Type;
25 import java.net.MalformedURLException;
27 import java.util.Base64;
28 import java.util.Date;
30 import javax.annotation.PostConstruct;
31 import javax.servlet.http.HttpServletResponse;
32 import javax.ws.rs.core.MediaType;
33 import javax.ws.rs.core.Response;
35 import org.apache.cxf.jaxrs.client.WebClient;
36 import org.apache.cxf.transport.http.HTTPException;
37 import org.openecomp.portalapp.portal.domain.EPApp;
38 import org.openecomp.portalapp.portal.logging.aop.EPAuditLog;
39 import org.openecomp.portalapp.portal.logging.aop.EPMetricsLog;
40 import org.openecomp.portalapp.portal.logging.format.EPAppMessagesEnum;
41 import org.openecomp.portalapp.portal.logging.logic.EPLogUtil;
42 import org.openecomp.portalapp.portal.utils.EPCommonSystemProperties;
43 import org.openecomp.portalapp.portal.utils.EcompPortalUtils;
44 import org.openecomp.portalapp.util.SystemType;
45 import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
46 import org.openecomp.portalsdk.core.onboarding.util.CipherUtil;
47 import org.openecomp.portalsdk.core.util.SystemProperties;
49 import org.springframework.beans.factory.annotation.Autowired;
50 import org.springframework.context.annotation.EnableAspectJAutoProxy;
51 import org.springframework.stereotype.Service;
53 import com.fasterxml.jackson.databind.ObjectMapper;
54 import com.google.gson.Gson;
55 import com.google.gson.GsonBuilder;
56 import com.google.gson.JsonDeserializationContext;
57 import com.google.gson.JsonDeserializer;
58 import com.google.gson.JsonElement;
59 import com.google.gson.JsonParseException;
61 @Service("applicationsRestClientService")
62 @org.springframework.context.annotation.Configuration
63 @EnableAspectJAutoProxy
65 public class ApplicationsRestClientServiceImpl implements ApplicationsRestClientService {
67 private static final String PASSWORD_HEADER = "password";
69 private static final String APP_USERNAME_HEADER = "username";
71 private static final String BASIC_AUTHENTICATION_HEADER = "Authorization";
73 private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ApplicationsRestClientServiceImpl.class);
76 private AppsCacheService appsCacheService;
80 private final ObjectMapper mapper = new ObjectMapper();
84 logger.debug(EELFLoggerDelegate.debugLogger, "initializing");
85 GsonBuilder builder = new GsonBuilder();
87 // Register an adapter to manage the date types as long values
88 builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
89 public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
90 throws JsonParseException {
91 return new Date(json.getAsJsonPrimitive().getAsLong());
95 gson = builder.create();
98 // TODO: do we need to do additional logging for remote API calls?
99 private static WebClient createClientForPath(String baseUri, String path) {
100 logger.info(EELFLoggerDelegate.debugLogger, "Creating web client for " + baseUri + " + " + path);
101 WebClient client = WebClient.create(baseUri);
102 client.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
108 private void verifyResponse(Response response) throws HTTPException {
109 int status = response.getStatus();
110 logger.debug(EELFLoggerDelegate.debugLogger, "http response status=" + status);
111 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE, Integer.toString(status));
112 if (!isHttpSuccess(status)) {
113 String errMsg = "Failed. Status=" + status + "; [" + response.getStatusInfo().getReasonPhrase().toString()
117 // must not be null to avoid NPE in HTTPException constructor
118 url = new URL("http://null");
119 if (response.getLocation() != null)
120 url = response.getLocation().toURL();
121 } catch (MalformedURLException e) {
122 // never mind. it is only for the debug message.
123 logger.warn(EELFLoggerDelegate.errorLogger, "Failed to build URL", e);
125 logger.error(EELFLoggerDelegate.errorLogger, "http response failed. " + errMsg + "; url=" + url);
126 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeIncorrectHttpStatusError);
127 throw new HTTPException(status, errMsg, url);
131 private static boolean isHttpSuccess(int status) {
132 return status / 100 == 2;
136 private WebClient createClientForApp(long appId, String restPath) {
137 return createClientFor(appId, restPath, SystemType.APPLICATION);
140 //TODO Need to implement the mylogins once the endpoint is confirmed
142 private WebClient createClientFor(long appSystemId, String restPath, SystemType type) {
143 logger.debug(EELFLoggerDelegate.debugLogger, "creating client for appId=" + appSystemId + "; restPath=" + restPath);
144 EPApp externalApp = null;
146 if(type == SystemType.APPLICATION){
147 externalApp = appsCacheService.getApp(appSystemId);
152 if (externalApp != null) {
153 String appBaseUri = (type == SystemType.APPLICATION) ? externalApp.getAppRestEndpoint() : "";
154 String username = (type == SystemType.APPLICATION) ? externalApp.getUsername(): "";
155 String encriptedPwd = (type == SystemType.APPLICATION) ? externalApp.getAppPassword(): "";
156 String appName = (type == SystemType.APPLICATION) ? externalApp.getName(): "";
157 String decreptedAppPwd = "";
160 MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTP);
161 if (appBaseUri != null && appBaseUri.contains("https")) {
162 MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTPS);
164 MDC.put(EPCommonSystemProperties.FULL_URL, appBaseUri + restPath);
165 MDC.put(EPCommonSystemProperties.TARGET_ENTITY, appName);
166 MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, restPath);
169 decreptedAppPwd = CipherUtil.decrypt(encriptedPwd,
170 SystemProperties.getProperty(SystemProperties.Decryption_Key));
171 } catch (Exception e) {
172 logger.error(EELFLoggerDelegate.errorLogger, "Unable to decrypt App name = " + externalApp,
173 EcompPortalUtils.getStackTrace(e));
174 logger.error(EELFLoggerDelegate.errorLogger, "Unable to decrypt App name = " + externalApp,
175 EcompPortalUtils.getStackTrace(e));
178 WebClient client = createClientForPath(appBaseUri, restPath);
180 // support basic authentication for some partners
181 String encoding = Base64.getEncoder().encodeToString((username + ":" + decreptedAppPwd).getBytes());
182 String encodingStr = "Basic " + encoding;
183 client.header(BASIC_AUTHENTICATION_HEADER, encodingStr);
185 // But still keep code downward compatible for non compliant apps
186 client.header(APP_USERNAME_HEADER, username);
187 client.header(PASSWORD_HEADER, decreptedAppPwd);
189 client.header(SystemProperties.ECOMP_REQUEST_ID, MDC.get(MDC_KEY_REQUEST_ID));
190 client.header(SystemProperties.USERAGENT_NAME, EPCommonSystemProperties.ECOMP_PORTAL_BE);
192 logger.debug(EELFLoggerDelegate.debugLogger,
193 String.format("App %d found, baseUri=[%s], Headers: [%s=%s, %s=%s, %s=%s]", appSystemId, appBaseUri,
194 APP_USERNAME_HEADER, username, PASSWORD_HEADER, encriptedPwd, BASIC_AUTHENTICATION_HEADER, encodingStr));
202 public <T> T get(Class<T> clazz, long appId, String restPath) throws HTTPException {
204 Response response = getResponse(appId, restPath);
206 if (response != null) {
207 verifyResponse(response);
208 String str = response.readEntity(String.class);
209 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
211 t = gson.fromJson(str, clazz);
212 } catch (Exception e) {
213 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
221 public String getIncomingJsonString(long appId, String restPath) throws HTTPException {
222 Response response = getResponse(appId, restPath);
224 if (response != null) {
225 verifyResponse(response);
226 String incomingJson = response.readEntity(String.class);
238 * org.openecomp.portalapp.portal.service.ApplicationsRestClientService#get(
239 * java.lang.Class, long, java.lang.String, boolean)
242 public <T> T get(Class<T> clazz, long appId, String restPath, boolean useJacksonMapper) throws HTTPException {
244 if (!useJacksonMapper)
245 return get(clazz, appId, restPath);
248 Response response = getResponse(appId, restPath);
250 if (response != null) {
251 verifyResponse(response);
252 String str = response.readEntity(String.class);
253 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
256 t = mapper.readValue(str, clazz);
257 } catch (Exception e) {
259 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
266 protected Response getResponse(long appId, String restPath) {
267 WebClient webClient = null;
268 Response response = null;
270 webClient = createClientForApp(appId, restPath);
271 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET request =", "no-payload");
274 if (webClient != null) {
275 response = webClient.get();
277 logger.error(EELFLoggerDelegate.errorLogger,
278 "Unable to create the Webclient to make the '" + restPath + "' API call.");
280 } catch (Exception e) {
281 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
282 Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
283 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
284 logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the GET REST API call", e);
291 public <T> T post(Class<T> clazz, long appId, Object payload, String restPath, SystemType type) throws HTTPException {
292 WebClient client = null;
293 Response response = null;
296 client = createClientFor(appId, restPath, type);
297 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST request =", payload);
300 if (client != null) {
301 response = client.post(payload);
303 logger.error(EELFLoggerDelegate.errorLogger,
304 "Unable to create the Webclient to make the '" + restPath + "' API call.");
306 } catch (Exception e) {
307 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
308 Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
309 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
310 logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the POST REST API call", e);
313 if (response != null) {
314 verifyResponse(response);
316 // String contentType = response.getHeaderString("Content-Type");
318 String str = response.readEntity(String.class);
319 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
321 t = gson.fromJson(str, clazz);
322 } catch (Exception e) {
323 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
331 public <T> T post(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
332 return post( clazz, appId, payload, restPath, SystemType.APPLICATION);
336 public <T> T postForClass(Class<T> clazz, long appId, Object payload, String restPath, Class<T> forClass) throws HTTPException {
337 WebClient client = null;
338 Response response = null;
341 client = createClientForApp(appId, restPath);
342 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST request =", payload);
345 if (client != null) {
346 response = client.post(payload);
348 logger.error(EELFLoggerDelegate.errorLogger,
349 "Unable to create the Webclient to make the '" + restPath + "' API call.");
351 } catch (Exception e) {
352 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
353 Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
354 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
355 logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the POST REST API call", e);
358 if (response != null) {
359 verifyResponse(response);
361 // String contentType = response.getHeaderString("Content-Type");
363 String str = response.readEntity(String.class);
364 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
366 t = gson.fromJson(str, clazz);
367 } catch (Exception e) {
368 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
377 public <T> T put(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
378 WebClient client = null;
379 Response response = null;
382 client = createClientForApp(appId, restPath);
383 EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT request =", payload);
386 if (client != null) {
387 response = client.put(payload);
389 logger.error(EELFLoggerDelegate.errorLogger,
390 "Unable to create the Webclient to make the '" + restPath + "' API call.");
392 } catch (Exception e) {
393 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
394 Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
395 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
396 logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the PUT REST API call", e);
399 if (response != null) {
400 verifyResponse(response);
401 String str = response.readEntity(String.class);
402 EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT result =", str);
404 t = gson.fromJson(str, clazz);
405 } catch (Exception e) {
406 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);