/*- * ============LICENSE_START======================================================= * org.openecomp.aai * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. * ============LICENSE_END========================================================= */ package org.openecomp.aai.restcore; import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; import com.google.common.base.Joiner; import org.openecomp.aai.db.props.AAIProperties; import org.openecomp.aai.dbmap.DBConnectionType; import org.openecomp.aai.exceptions.AAIException; import org.openecomp.aai.introspection.Introspector; import org.openecomp.aai.introspection.Loader; import org.openecomp.aai.introspection.tools.*; import org.openecomp.aai.logging.ErrorLogHelper; import org.openecomp.aai.util.AAIConfig; import org.openecomp.aai.util.AAIConstants; import org.openecomp.aai.util.AAITxnLog; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import java.io.UnsupportedEncodingException; import java.net.URI; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Base class for AAI REST API classes. * Provides method to validate header information * TODO should authenticate caller and authorize them for the API they are calling * TODO should store the transaction * */ public class RESTAPI { private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(RESTAPI.class); protected final String COMPONENT = "aairest"; /** * The Enum Action. */ public enum Action { GET, PUT, POST, DELETE }; public AAITxnLog txn = null; /** * Gets the from app id. * * @param headers the headers * @param logline the logline * @return the from app id * @throws AAIException the AAI exception */ protected String getFromAppId(HttpHeaders headers) throws AAIException { String fromAppId = null; if (headers != null) { List fromAppIdHeader = headers.getRequestHeader("X-FromAppId"); if (fromAppIdHeader != null) { for (String fromAppIdValue : fromAppIdHeader) { fromAppId = fromAppIdValue; } } } if (fromAppId == null) { throw new AAIException("AAI_4009"); } return fromAppId; } /** * Gets the trans id. * * @param headers the headers * @param logline the logline * @return the trans id * @throws AAIException the AAI exception */ protected String getTransId(HttpHeaders headers) throws AAIException { String transId = null; if (headers != null) { List transIdHeader = headers.getRequestHeader("X-TransactionId"); if (transIdHeader != null) { for (String transIdValue : transIdHeader) { transId = transIdValue; } } } if (transId == null) { throw new AAIException("AAI_4010"); } return transId; } /** * Gen date. * * @return the string */ protected String genDate() { Date date = new Date(); DateFormat formatter = null; try { formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT)); } catch (AAIException ex) { ErrorLogHelper.logException(ex); } finally { if (formatter == null) { formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS"); } } return formatter.format(date); } /** * Gets the media type. * * @param mediaTypeList the media type list * @return the media type */ protected String getMediaType(List mediaTypeList) { String mediaType = MediaType.APPLICATION_JSON; // json is the default for (MediaType mt : mediaTypeList) { if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt)) { mediaType = MediaType.APPLICATION_XML; } } return mediaType; } /** * Log transaction. * * @param appId the app id * @param tId the t id * @param action the action * @param input the input * @param rqstTm the rqst tm * @param respTm the resp tm * @param request the request * @param response the response */ /* ---------------- Log Transaction into HBase --------------------- */ public void logTransaction( String appId, String tId, String action, String input, String rqstTm, String respTm, String request, Response response) { String respBuf = ""; int status = 0; if (response != null && response.getEntity() != null) { respBuf = response.getEntity().toString(); status = response.getStatus(); } logTransaction(appId, tId, action, input, rqstTm, respTm, request, respBuf, String.valueOf(status)); } /** * Log transaction. * * @param appId the app id * @param tId the t id * @param action the action * @param input the input * @param rqstTm the rqst tm * @param respTm the resp tm * @param request the request * @param respBuf the resp buf * @param status the status * @param logline the logline */ public void logTransaction( String appId, String tId, String action, String input, String rqstTm, String respTm, String request, String respBuf, String status) { try { // we only run this way if we're not doing it in the CXF interceptor if (!AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_INTERCEPTOR).equalsIgnoreCase("true")) { if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_ENABLED).equalsIgnoreCase("true")) { txn = new AAITxnLog(tId, appId); // tid, status, rqstTm, respTm, srcId, rsrcId, rsrcType, rqstBuf, respBuf String hbtid = txn.put(tId, status, rqstTm, respTm, appId, input, action, request, respBuf); LOGGER.debug("HbTransId={}",hbtid); LOGGER.debug("action={}", action); LOGGER.debug("urlin={}", input); } } } catch (AAIException e) { // i think we do nothing } } /* ----------helpers for common consumer actions ----------- */ /** * Sets the depth. * * @param depthParam the depth param * @return the int * @throws AAIException the AAI exception */ protected int setDepth(String depthParam) throws AAIException { int depth = AAIProperties.MAXIMUM_DEPTH; //default if (depthParam != null && depthParam.length() > 0 && !depthParam.equals("all")){ try { depth = Integer.valueOf(depthParam); } catch (Exception e) { throw new AAIException("AAI_4016"); } } return depth; } /** * Consumer exception response generator. * * @param headers the headers * @param info the info * @param templateAction the template action * @param e the e * @return the response */ protected Response consumerExceptionResponseGenerator(HttpHeaders headers, UriInfo info, HttpMethod templateAction, AAIException e) { ArrayList templateVars = new ArrayList(); templateVars.add(templateAction.toString()); //GET, PUT, etc templateVars.add(info.getPath().toString()); templateVars.addAll(e.getTemplateVars()); return Response .status(e.getErrorObject().getHTTPResponseCode()) .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(headers.getAcceptableMediaTypes(), e, templateVars)) .build(); } /** * Validate introspector. * * @param obj the obj * @param loader the loader * @param uri the uri * @param validateRequired the validate required * @throws AAIException the AAI exception * @throws UnsupportedEncodingException the unsupported encoding exception */ protected void validateIntrospector(Introspector obj, Loader loader, URI uri, HttpMethod method) throws AAIException, UnsupportedEncodingException { int maximumDepth = AAIProperties.MAXIMUM_DEPTH; boolean validateRequired = true; if (method.equals(HttpMethod.MERGE_PATCH)) { validateRequired = false; maximumDepth = 0; } IntrospectorValidator validator = new IntrospectorValidator.Builder() .validateRequired(validateRequired) .restrictDepth(maximumDepth) .addResolver(new RemoveNonVisibleProperty()) .addResolver(new CreateUUID()) .addResolver(new DefaultFields()) .addResolver(new InjectKeysFromURI(loader, uri)) .build(); boolean result = validator.validate(obj); if (!result) { result = validator.resolveIssues(); } if (!result) { List messages = new ArrayList<>(); for (Issue issue : validator.getIssues()) { if (!issue.isResolved()) { messages.add(issue.getDetail()); } } String errors = Joiner.on(",").join(messages); throw new AAIException("AAI_3000", errors); } //check that key in payload and key in request uri are the same String objURI = obj.getURI(); //if requested object is a parent objURI will have a leading slash the input uri will lack //this adds that leading slash for the comparison String testURI = "/" + uri.getRawPath(); if (!testURI.endsWith(objURI)) { throw new AAIException("AAI_3000", "uri and payload keys don't match"); } } protected DBConnectionType determineConnectionType(String fromAppId, String realTime) { DBConnectionType type = DBConnectionType.REALTIME; boolean isRealTimeClient = AAIConfig.get("aai.realtime.clients", "").contains(fromAppId); if (isRealTimeClient || realTime != null) { type = DBConnectionType.REALTIME; } else { type = DBConnectionType.CACHED; } return type; } /** * Gets the input media type. * * @param mediaType the media type * @return the input media type */ protected String getInputMediaType(MediaType mediaType) { String result = mediaType.getType() + "/" + mediaType.getSubtype(); return result; } }