package org.onap.vid.mso; import com.att.eelf.configuration.EELFLogger; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.codec.binary.Base64; import org.apache.http.HttpException; import org.eclipse.jetty.util.security.Password; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.aai.ExceptionWithRequestInfo; import org.onap.vid.aai.util.HttpClientMode; import org.onap.vid.aai.util.HttpsAuthClient; import org.onap.vid.client.HttpBasicClient; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.mso.rest.RestInterface; import org.onap.vid.utils.Logging; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import javax.ws.rs.client.Client; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.Response; import java.util.Collections; import java.util.Optional; import static org.onap.vid.utils.Logging.*; /** * Created by pickjonathan on 26/06/2017. */ public abstract class RestMsoImplementation implements RestInterface { /** * The logger. */ protected EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMsoImplementation.class); private final EELFLogger outgoingRequestsLogger = Logging.getRequestsLogger("mso"); /** The client. */ private Client client = null; @Autowired protected HttpsAuthClient httpsAuthClient; private static final String START_LOG = " start"; private static final String APPLICATION_JSON = "application/json"; private static final String WITH_STATUS = " with status="; private static final String URL_LOG = ", url="; private static final String NO_RESPONSE_ENTITY_LOG = " No response entity, this is probably ok, e="; private static final String WITH_URL_LOG = " with url="; private static final String EXCEPTION_LOG = ", Exception: "; private static final String REST_API_SUCCESSFULL_LOG = " REST api was successfull!"; private static final String REST_MSG_TEMPLATE = "start {}->{}({}, {}, {})"; /** The common headers. */ /** * Instantiates a new mso rest interface. */ @SuppressWarnings("Duplicates") protected MultivaluedHashMap initMsoClient() { final String methodname = "initRestClient()"; final String username = SystemProperties.getProperty(MsoProperties.MSO_USER_NAME); final String password = SystemProperties.getProperty(MsoProperties.MSO_PASSWORD); final String mso_url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL); final String decrypted_password = Password.deobfuscate(password); String authString = username + ":" + decrypted_password; byte[] authEncBytes = Base64.encodeBase64(authString.getBytes()); String authStringEnc = new String(authEncBytes); MultivaluedHashMap commonHeaders = new MultivaluedHashMap(); commonHeaders.put("Authorization", Collections.singletonList(("Basic " + authStringEnc))); commonHeaders.put("X-ONAP-PartnerName", Collections.singletonList("VID")); String requestIdValue = Logging.extractOrGenerateRequestId(); commonHeaders.put(REQUEST_ID_HEADER_KEY, Collections.singletonList(requestIdValue)); commonHeaders.put(ONAP_REQUEST_ID_HEADER_KEY, Collections.singletonList(requestIdValue)); boolean useSsl = true; if ( (mso_url != null) && ( !(mso_url.isEmpty()) ) ) { useSsl = mso_url.startsWith("https"); } if (client == null) { try { if ( useSsl ) { client = httpsAuthClient.getClient(HttpClientMode.WITHOUT_KEYSTORE); } else { client = HttpBasicClient.getClient(); } } catch (Exception e) { logger.info(EELFLoggerDelegate.errorLogger,methodname + " Unable to get the SSL client"); } } return commonHeaders; } public RestObjectWithRequestInfo Get(T t, String path, RestObject restObject, boolean warpException) { String methodName = "Get"; logger.debug(EELFLoggerDelegate.debugLogger, methodName + START_LOG); String url = null; String rawData = null; Integer status = null; try { restObject.set(t); url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; MultivaluedHashMap commonHeaders = initMsoClient(); Logging.logRequest(outgoingRequestsLogger, HttpMethod.GET, url); final Response cres = client.target(url) .request() .accept(APPLICATION_JSON) .headers(commonHeaders) .get(); Logging.logResponse(outgoingRequestsLogger, HttpMethod.GET, url, cres); cres.bufferEntity(); status = cres.getStatus(); rawData = cres.readEntity(String.class); restObject.setStatusCode(status); if (status == 200 || status == 202) { t = (T) cres.readEntity(t.getClass()); restObject.set(t); logger.debug(EELFLoggerDelegate.debugLogger, methodName + REST_API_SUCCESSFULL_LOG); } else { throw new GenericUncheckedException(new HttpException(methodName + WITH_STATUS + status + " (200 or 202 expected), url= " + url)); } logger.debug(EELFLoggerDelegate.debugLogger, methodName + " received status=" + status); return new RestObjectWithRequestInfo<>(HttpMethod.GET, url, restObject, status, rawData); } catch (RuntimeException e) { throw warpException ? new ExceptionWithRequestInfo(HttpMethod.GET, url, rawData, status, e) : e; } } @Override public RestObject GetForObject(String path, Class clazz) { final String methodName = getMethodName(); logger.debug(EELFLoggerDelegate.debugLogger, "start {}->{}({}, {})", getMethodCallerName(), methodName, path, clazz); String url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; logger.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + " sending request to url= " + url); MultivaluedHashMap commonHeaders = initMsoClient(); Logging.logRequest(outgoingRequestsLogger, HttpMethod.GET, url); final Response cres = client.target(url) .request() .accept(APPLICATION_JSON) .headers(commonHeaders) .get(); Logging.logResponse(outgoingRequestsLogger, HttpMethod.GET, url, cres); final RestObject restObject = cresToRestObject(cres, clazz); int status = cres.getStatus(); if (status == 200 || status == 202) { logger.debug(EELFLoggerDelegate.debugLogger, methodName + REST_API_SUCCESSFULL_LOG); } else { logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_STATUS +status+ URL_LOG +url); } logger.debug(EELFLoggerDelegate.debugLogger,methodName + " received status=" + status ); return restObject; } @Override public void Delete(T t, Object r, String path, RestObject restObject) { String methodName = "Delete"; String url=""; Response cres; logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + START_LOG); try { MultivaluedHashMap commonHeaders = initMsoClient(); url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; Logging.logRequest(outgoingRequestsLogger, HttpMethod.DELETE, url, r); cres = client.target(url) .request() .accept(APPLICATION_JSON) .headers(commonHeaders) //.entity(r) .build("DELETE", Entity.entity(r, MediaType.APPLICATION_JSON)).invoke(); Logging.logResponse(outgoingRequestsLogger, HttpMethod.DELETE, url, cres); int status = cres.getStatus(); restObject.setStatusCode (status); if (status == 404) { // resource not found String msg = "Resource does not exist...: " + cres.getStatus(); logger.debug(EELFLoggerDelegate.debugLogger,"<== " + msg); } else if (status == 200 || status == 204){ logger.debug(EELFLoggerDelegate.debugLogger,"<== " + "Resource " + url + " deleted"); } else if (status == 202) { String msg = "Delete in progress: " + status; logger.debug(EELFLoggerDelegate.debugLogger,"<== " + msg); } else { String msg = "Deleting Resource failed: " + status; logger.debug(EELFLoggerDelegate.debugLogger,"<== " + msg); } try { t = (T) cres.readEntity(t.getClass()); restObject.set(t); } catch ( Exception e ) { logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + NO_RESPONSE_ENTITY_LOG + e.getMessage()); } } catch (Exception e) { logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_URL_LOG +url+ EXCEPTION_LOG + e.toString()); throw e; } } public RestObject PostForObject(Object requestDetails, String path, Class clazz) { logger.debug(EELFLoggerDelegate.debugLogger, REST_MSG_TEMPLATE, getMethodCallerName(), getMethodName(), requestDetails, path, clazz); return restCall(HttpMethod.POST, clazz, requestDetails, path); } public RestObject DeleteForObject(Object requestDetails, String path, Class clazz) { logger.debug(EELFLoggerDelegate.debugLogger, REST_MSG_TEMPLATE, getMethodCallerName(), getMethodName(), requestDetails, path, clazz); return restCall(HttpMethod.DELETE, clazz, requestDetails, path); } @Override public void Post(String t, Object r, String path, RestObject restObject) { logger.debug(EELFLoggerDelegate.debugLogger, REST_MSG_TEMPLATE, getMethodCallerName(), getMethodName(), t.getClass(), r, path); restObject.copyFrom(restCall(HttpMethod.POST, String.class, r, path)); } public Invocation.Builder prepareClient(String path, String methodName) { MultivaluedHashMap commonHeaders = initMsoClient(); String url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + " sending request to url= " + url); // Change the content length return client.target(url) .request() .accept(APPLICATION_JSON) .headers(commonHeaders); } public RestObject restCall(HttpMethod httpMethod, Class tClass, Object payload, String path) { return restCall(httpMethod, tClass, payload, path, Optional.empty()); } /* user id is needed to be pass as X-RequestorID in new MSO flows like Delete instanceGroup */ public RestObject restCall(HttpMethod httpMethod, Class tClass, Object payload, String path, Optional userId) { String methodName = httpMethod.name(); String url=""; try { MultivaluedHashMap commonHeaders = initMsoClient(); userId.ifPresent(id->commonHeaders.put("X-RequestorID", Collections.singletonList(id))); url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; Logging.logRequest(outgoingRequestsLogger, httpMethod, url, payload); // Change the content length final Invocation.Builder restBuilder = client.target(url) .request() .accept(APPLICATION_JSON) .headers(commonHeaders); Invocation restInvocation = payload==null ? restBuilder.build(httpMethod.name()) : restBuilder.build(httpMethod.name(), Entity.entity(payload, MediaType.APPLICATION_JSON)); final Response cres = restInvocation.invoke(); Logging.logResponse(outgoingRequestsLogger, httpMethod, url, cres); return cresToRestObject(cres, tClass); } catch (Exception e) { logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_URL_LOG +url+ EXCEPTION_LOG + e.toString()); throw e; } } private RestObject cresToRestObject(Response cres, Class tClass) { RestObject restObject = new RestObject<>(); String rawEntity = null; try { cres.bufferEntity(); rawEntity = cres.readEntity(String.class); restObject.setRaw(rawEntity); T t = (T) new ObjectMapper().readValue(rawEntity, tClass); restObject.set(t); } catch ( Exception e ) { try { logger.debug(EELFLoggerDelegate.debugLogger, "<== " + getMethodCallerName() + " Error reading response entity as " + tClass + ": , e=" + e.getMessage() + ", Entity=" + rawEntity); } catch (Exception e2) { logger.debug(EELFLoggerDelegate.debugLogger, "<== " + getMethodCallerName() + NO_RESPONSE_ENTITY_LOG + e.getMessage()); } } int status = cres.getStatus(); restObject.setStatusCode (status); return restObject; } @Override public void Put(T t, org.onap.vid.changeManagement.RequestDetailsWrapper r, String path, RestObject restObject) { String methodName = "Put"; String url=""; logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + START_LOG); try { MultivaluedHashMap commonHeaders = initMsoClient(); url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; Logging.logRequest(outgoingRequestsLogger, HttpMethod.PUT, url, r); // Change the content length final Response cres = client.target(url) .request() .accept(APPLICATION_JSON) .headers(commonHeaders) //.header("content-length", 201) .put(Entity.entity(r, MediaType.APPLICATION_JSON)); Logging.logResponse(outgoingRequestsLogger, HttpMethod.PUT, url, cres); try { t = (T) cres.readEntity(t.getClass()); restObject.set(t); } catch ( Exception e ) { logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + NO_RESPONSE_ENTITY_LOG + e.getMessage()); } int status = cres.getStatus(); restObject.setStatusCode (status); if ( status >= 200 && status <= 299 ) { logger.info(EELFLoggerDelegate.errorLogger, "<== " + methodName + REST_API_SUCCESSFULL_LOG); logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + REST_API_SUCCESSFULL_LOG); } else { logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_STATUS +status+ URL_LOG +url); } } catch (Exception e) { logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_URL_LOG +url+ EXCEPTION_LOG + e.toString()); throw e; } } }