2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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 * ============LICENSE_END=========================================================
21 package org.openecomp.aai.restcore;
23 import com.att.eelf.configuration.EELFLogger;
24 import com.att.eelf.configuration.EELFManager;
25 import com.google.common.base.Joiner;
26 import org.openecomp.aai.db.props.AAIProperties;
27 import org.openecomp.aai.dbmap.DBConnectionType;
28 import org.openecomp.aai.exceptions.AAIException;
29 import org.openecomp.aai.introspection.Introspector;
30 import org.openecomp.aai.introspection.Loader;
31 import org.openecomp.aai.introspection.tools.*;
32 import org.openecomp.aai.logging.ErrorLogHelper;
33 import org.openecomp.aai.util.AAIConfig;
34 import org.openecomp.aai.util.AAIConstants;
35 import org.openecomp.aai.util.AAITxnLog;
37 import javax.ws.rs.core.HttpHeaders;
38 import javax.ws.rs.core.MediaType;
39 import javax.ws.rs.core.Response;
40 import javax.ws.rs.core.UriInfo;
41 import java.io.UnsupportedEncodingException;
43 import java.text.DateFormat;
44 import java.text.SimpleDateFormat;
45 import java.util.ArrayList;
46 import java.util.Date;
47 import java.util.List;
51 * Base class for AAI REST API classes.
52 * Provides method to validate header information
53 * TODO should authenticate caller and authorize them for the API they are calling
54 * TODO should store the transaction
58 public class RESTAPI {
60 private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(RESTAPI.class);
62 protected final String COMPONENT = "aairest";
68 GET, PUT, POST, DELETE
72 public AAITxnLog txn = null;
75 * Gets the from app id.
77 * @param headers the headers
78 * @param logline the logline
79 * @return the from app id
80 * @throws AAIException the AAI exception
82 protected String getFromAppId(HttpHeaders headers) throws AAIException {
83 String fromAppId = null;
84 if (headers != null) {
85 List<String> fromAppIdHeader = headers.getRequestHeader("X-FromAppId");
86 if (fromAppIdHeader != null) {
87 for (String fromAppIdValue : fromAppIdHeader) {
88 fromAppId = fromAppIdValue;
93 if (fromAppId == null) {
94 throw new AAIException("AAI_4009");
103 * @param headers the headers
104 * @param logline the logline
105 * @return the trans id
106 * @throws AAIException the AAI exception
108 protected String getTransId(HttpHeaders headers) throws AAIException {
109 String transId = null;
110 if (headers != null) {
111 List<String> transIdHeader = headers.getRequestHeader("X-TransactionId");
112 if (transIdHeader != null) {
113 for (String transIdValue : transIdHeader) {
114 transId = transIdValue;
119 if (transId == null) {
120 throw new AAIException("AAI_4010");
132 protected String genDate() {
133 Date date = new Date();
134 DateFormat formatter = null;
136 formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
137 } catch (AAIException ex) {
138 ErrorLogHelper.logException(ex);
140 if (formatter == null) {
141 formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
145 return formatter.format(date);
149 * Gets the media type.
151 * @param mediaTypeList the media type list
152 * @return the media type
154 protected String getMediaType(List <MediaType> mediaTypeList) {
155 String mediaType = MediaType.APPLICATION_JSON; // json is the default
156 for (MediaType mt : mediaTypeList) {
157 if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt)) {
158 mediaType = MediaType.APPLICATION_XML;
168 * @param appId the app id
169 * @param tId the t id
170 * @param action the action
171 * @param input the input
172 * @param rqstTm the rqst tm
173 * @param respTm the resp tm
174 * @param request the request
175 * @param response the response
177 /* ---------------- Log Transaction into HBase --------------------- */
178 public void logTransaction( String appId, String tId, String action,
179 String input, String rqstTm, String respTm, String request, Response response) {
183 if (response != null && response.getEntity() != null) {
184 respBuf = response.getEntity().toString();
185 status = response.getStatus();
187 logTransaction(appId, tId, action, input, rqstTm, respTm, request, respBuf, String.valueOf(status));
193 * @param appId the app id
194 * @param tId the t id
195 * @param action the action
196 * @param input the input
197 * @param rqstTm the rqst tm
198 * @param respTm the resp tm
199 * @param request the request
200 * @param respBuf the resp buf
201 * @param status the status
202 * @param logline the logline
204 public void logTransaction( String appId, String tId, String action,
205 String input, String rqstTm, String respTm, String request, String respBuf, String status) {
207 // we only run this way if we're not doing it in the CXF interceptor
208 if (!AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_INTERCEPTOR).equalsIgnoreCase("true")) {
209 if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_ENABLED).equalsIgnoreCase("true")) {
210 txn = new AAITxnLog(tId, appId);
211 // tid, status, rqstTm, respTm, srcId, rsrcId, rsrcType, rqstBuf, respBuf
212 String hbtid = txn.put(tId, status,
213 rqstTm, respTm, appId, input, action, request, respBuf);
215 LOGGER.debug("HbTransId={}",hbtid);
216 LOGGER.debug("action={}", action);
217 LOGGER.debug("urlin={}", input);
221 } catch (AAIException e) {
222 // i think we do nothing
226 /* ----------helpers for common consumer actions ----------- */
231 * @param depthParam the depth param
233 * @throws AAIException the AAI exception
235 protected int setDepth(String depthParam) throws AAIException {
236 int depth = AAIProperties.MAXIMUM_DEPTH; //default
237 if (depthParam != null && depthParam.length() > 0 && !depthParam.equals("all")){
239 depth = Integer.valueOf(depthParam);
240 } catch (Exception e) {
241 throw new AAIException("AAI_4016");
248 * Consumer exception response generator.
250 * @param headers the headers
251 * @param info the info
252 * @param templateAction the template action
254 * @return the response
256 protected Response consumerExceptionResponseGenerator(HttpHeaders headers, UriInfo info, HttpMethod templateAction, AAIException e) {
257 ArrayList<String> templateVars = new ArrayList<String>();
258 templateVars.add(templateAction.toString()); //GET, PUT, etc
259 templateVars.add(info.getPath().toString());
260 templateVars.addAll(e.getTemplateVars());
263 .status(e.getErrorObject().getHTTPResponseCode())
264 .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(headers.getAcceptableMediaTypes(), e, templateVars))
269 * Validate introspector.
272 * @param loader the loader
274 * @param validateRequired the validate required
275 * @throws AAIException the AAI exception
276 * @throws UnsupportedEncodingException the unsupported encoding exception
278 protected void validateIntrospector(Introspector obj, Loader loader, URI uri, HttpMethod method) throws AAIException, UnsupportedEncodingException {
280 int maximumDepth = AAIProperties.MAXIMUM_DEPTH;
281 boolean validateRequired = true;
282 if (method.equals(HttpMethod.MERGE_PATCH)) {
283 validateRequired = false;
286 IntrospectorValidator validator = new IntrospectorValidator.Builder()
287 .validateRequired(validateRequired)
288 .restrictDepth(maximumDepth)
289 .addResolver(new RemoveNonVisibleProperty())
290 .addResolver(new CreateUUID())
291 .addResolver(new DefaultFields())
292 .addResolver(new InjectKeysFromURI(loader, uri))
294 boolean result = validator.validate(obj);
296 result = validator.resolveIssues();
299 List<String> messages = new ArrayList<>();
300 for (Issue issue : validator.getIssues()) {
301 if (!issue.isResolved()) {
302 messages.add(issue.getDetail());
305 String errors = Joiner.on(",").join(messages);
306 throw new AAIException("AAI_3000", errors);
308 //check that key in payload and key in request uri are the same
309 String objURI = obj.getURI();
310 //if requested object is a parent objURI will have a leading slash the input uri will lack
311 //this adds that leading slash for the comparison
312 String testURI = "/" + uri.getRawPath();
313 if (!testURI.endsWith(objURI)) {
314 throw new AAIException("AAI_3000", "uri and payload keys don't match");
318 protected DBConnectionType determineConnectionType(String fromAppId, String realTime) {
319 DBConnectionType type = DBConnectionType.REALTIME;
320 boolean isRealTimeClient = AAIConfig.get("aai.realtime.clients", "").contains(fromAppId);
321 if (isRealTimeClient || realTime != null) {
322 type = DBConnectionType.REALTIME;
324 type = DBConnectionType.CACHED;
331 * Gets the input media type.
333 * @param mediaType the media type
334 * @return the input media type
336 protected String getInputMediaType(MediaType mediaType) {
337 String result = mediaType.getType() + "/" + mediaType.getSubtype();