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 java.io.StringReader;
24 import java.io.UnsupportedEncodingException;
26 import java.text.DateFormat;
27 import java.text.SimpleDateFormat;
28 import java.util.ArrayList;
29 import java.util.Date;
30 import java.util.List;
32 import javax.ws.rs.core.HttpHeaders;
33 import javax.ws.rs.core.MediaType;
34 import javax.ws.rs.core.Response;
35 import javax.ws.rs.core.UriInfo;
36 import javax.xml.bind.JAXBException;
37 import javax.xml.transform.stream.StreamSource;
39 import org.eclipse.persistence.dynamic.DynamicEntity;
40 import org.eclipse.persistence.jaxb.JAXBUnmarshaller;
41 import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
43 import org.openecomp.aai.db.props.AAIProperties;
44 import org.openecomp.aai.dbmap.DBConnectionType;
45 import org.openecomp.aai.domain.model.AAIResource;
46 import org.openecomp.aai.exceptions.AAIException;
47 import org.openecomp.aai.introspection.Introspector;
48 import org.openecomp.aai.introspection.Loader;
49 import org.openecomp.aai.introspection.tools.CreateUUID;
50 import org.openecomp.aai.introspection.tools.DefaultFields;
51 import org.openecomp.aai.introspection.tools.InjectKeysFromURI;
52 import org.openecomp.aai.introspection.tools.IntrospectorValidator;
53 import org.openecomp.aai.introspection.tools.Issue;
54 import org.openecomp.aai.introspection.tools.RemoveNonVisibleProperty;
55 import org.openecomp.aai.logging.ErrorLogHelper;
56 import org.openecomp.aai.logging.LoggingContext;
57 import org.openecomp.aai.util.AAIConfig;
58 import org.openecomp.aai.util.AAIConstants;
59 import org.openecomp.aai.util.AAITxnLog;
60 import com.att.eelf.configuration.EELFLogger;
61 import com.att.eelf.configuration.EELFManager;
62 import com.google.common.base.Joiner;
66 * Base class for AAI REST API classes.
67 * Provides method to validate header information
68 * TODO should authenticate caller and authorize them for the API they are calling
69 * TODO should store the transaction
73 public class RESTAPI {
75 private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(RESTAPI.class);
77 protected final String COMPONENT = "aairest";
83 GET, PUT, POST, DELETE
87 public AAITxnLog txn = null;
90 * Gets the from app id.
92 * @param headers the headers
93 * @param logline the logline
94 * @return the from app id
95 * @throws AAIException the AAI exception
97 protected String getFromAppId(HttpHeaders headers) throws AAIException {
98 String fromAppId = null;
99 if (headers != null) {
100 List<String> fromAppIdHeader = headers.getRequestHeader("X-FromAppId");
101 if (fromAppIdHeader != null) {
102 for (String fromAppIdValue : fromAppIdHeader) {
103 fromAppId = fromAppIdValue;
108 if (fromAppId == null) {
109 throw new AAIException("AAI_4009");
112 LoggingContext.partnerName(fromAppId);
120 * @param headers the headers
121 * @param logline the logline
122 * @return the trans id
123 * @throws AAIException the AAI exception
125 protected String getTransId(HttpHeaders headers) throws AAIException {
126 String transId = null;
127 if (headers != null) {
128 List<String> transIdHeader = headers.getRequestHeader("X-TransactionId");
129 if (transIdHeader != null) {
130 for (String transIdValue : transIdHeader) {
131 transId = transIdValue;
136 if (transId == null) {
137 throw new AAIException("AAI_4010");
140 LoggingContext.requestId(transId);
151 protected String genDate() {
152 Date date = new Date();
153 DateFormat formatter = null;
155 formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
156 } catch (AAIException ex) {
157 ErrorLogHelper.logException(ex);
159 if (formatter == null) {
160 formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
164 return formatter.format(date);
168 * Gets the media type.
170 * @param mediaTypeList the media type list
171 * @return the media type
173 protected String getMediaType(List <MediaType> mediaTypeList) {
174 String mediaType = MediaType.APPLICATION_JSON; // json is the default
175 for (MediaType mt : mediaTypeList) {
176 if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt)) {
177 mediaType = MediaType.APPLICATION_XML;
187 * @param appId the app id
188 * @param tId the t id
189 * @param action the action
190 * @param input the input
191 * @param rqstTm the rqst tm
192 * @param respTm the resp tm
193 * @param request the request
194 * @param response the response
196 /* ---------------- Log Transaction into HBase --------------------- */
197 public void logTransaction( String appId, String tId, String action,
198 String input, String rqstTm, String respTm, String request, Response response) {
202 if (response != null && response.getEntity() != null) {
203 respBuf = response.getEntity().toString();
204 status = response.getStatus();
206 logTransaction(appId, tId, action, input, rqstTm, respTm, request, respBuf, String.valueOf(status));
212 * @param appId the app id
213 * @param tId the t id
214 * @param action the action
215 * @param input the input
216 * @param rqstTm the rqst tm
217 * @param respTm the resp tm
218 * @param request the request
219 * @param respBuf the resp buf
220 * @param status the status
221 * @param logline the logline
223 public void logTransaction( String appId, String tId, String action,
224 String input, String rqstTm, String respTm, String request, String respBuf, String status) {
226 // we only run this way if we're not doing it in the CXF interceptor
227 if (!AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_INTERCEPTOR).equalsIgnoreCase("true")) {
228 if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_ENABLED).equalsIgnoreCase("true")) {
229 txn = new AAITxnLog(tId, appId);
230 // tid, status, rqstTm, respTm, srcId, rsrcId, rsrcType, rqstBuf, respBuf
231 String hbtid = txn.put(tId, status,
232 rqstTm, respTm, appId, input, action, request, respBuf);
234 LOGGER.debug("HbTransId={}",hbtid);
235 LOGGER.debug("action={}", action);
236 LOGGER.debug("urlin={}", input);
240 } catch (AAIException e) {
241 // i think we do nothing
245 /* ----------helpers for common consumer actions ----------- */
250 * @param depthParam the depth param
252 * @throws AAIException the AAI exception
254 protected int setDepth(String depthParam) throws AAIException {
255 int depth = AAIProperties.MAXIMUM_DEPTH; //default
256 if (depthParam != null && depthParam.length() > 0 && !depthParam.equals("all")){
258 depth = Integer.valueOf(depthParam);
259 } catch (Exception e) {
260 throw new AAIException("AAI_4016");
267 * Consumer exception response generator.
269 * @param headers the headers
270 * @param info the info
271 * @param templateAction the template action
273 * @return the response
275 protected Response consumerExceptionResponseGenerator(HttpHeaders headers, UriInfo info, HttpMethod templateAction, AAIException e) {
276 ArrayList<String> templateVars = new ArrayList<String>();
277 templateVars.add(templateAction.toString()); //GET, PUT, etc
278 templateVars.add(info.getPath().toString());
279 templateVars.addAll(e.getTemplateVars());
282 .status(e.getErrorObject().getHTTPResponseCode())
283 .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(headers.getAcceptableMediaTypes(), e, templateVars))
288 * Validate introspector.
291 * @param loader the loader
293 * @param validateRequired the validate required
294 * @throws AAIException the AAI exception
295 * @throws UnsupportedEncodingException the unsupported encoding exception
297 protected void validateIntrospector(Introspector obj, Loader loader, URI uri, HttpMethod method) throws AAIException, UnsupportedEncodingException {
299 int maximumDepth = AAIProperties.MAXIMUM_DEPTH;
300 boolean validateRequired = true;
301 if (method.equals(HttpMethod.MERGE_PATCH)) {
302 validateRequired = false;
305 IntrospectorValidator validator = new IntrospectorValidator.Builder()
306 .validateRequired(validateRequired)
307 .restrictDepth(maximumDepth)
308 .addResolver(new RemoveNonVisibleProperty())
309 .addResolver(new CreateUUID())
310 .addResolver(new DefaultFields())
311 .addResolver(new InjectKeysFromURI(loader, uri))
313 boolean result = validator.validate(obj);
315 result = validator.resolveIssues();
318 List<String> messages = new ArrayList<>();
319 for (Issue issue : validator.getIssues()) {
320 if (!issue.isResolved()) {
321 messages.add(issue.getDetail());
324 String errors = Joiner.on(",").join(messages);
325 throw new AAIException("AAI_3000", errors);
327 //check that key in payload and key in request uri are the same
328 String objURI = obj.getURI();
329 //if requested object is a parent objURI will have a leading slash the input uri will lack
330 //this adds that leading slash for the comparison
331 String testURI = "/" + uri.getRawPath();
332 if (!testURI.endsWith(objURI)) {
333 throw new AAIException("AAI_3000", "uri and payload keys don't match");
337 protected DBConnectionType determineConnectionType(String fromAppId, String realTime) {
338 DBConnectionType type = DBConnectionType.REALTIME;
339 boolean isRealTimeClient = AAIConfig.get("aai.realtime.clients", "").contains(fromAppId);
340 if (isRealTimeClient || realTime != null) {
341 type = DBConnectionType.REALTIME;
343 type = DBConnectionType.CACHED;
350 * Gets the input media type.
352 * @param mediaType the media type
353 * @return the input media type
355 protected String getInputMediaType(MediaType mediaType) {
356 String result = mediaType.getType() + "/" + mediaType.getSubtype();