[AAI-ONAP] Get the latest code and sync to onap
[aai/aai-common.git] / aai-core / src / main / java / org / openecomp / aai / restcore / RESTAPI.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * org.openecomp.aai
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.aai.restcore;
22
23 import java.io.UnsupportedEncodingException;
24 import java.net.URI;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import javax.ws.rs.core.HttpHeaders;
29 import javax.ws.rs.core.MediaType;
30 import javax.ws.rs.core.Response;
31 import javax.ws.rs.core.UriInfo;
32
33 import org.openecomp.aai.db.props.AAIProperties;
34 import org.openecomp.aai.dbmap.DBConnectionType;
35 import org.openecomp.aai.exceptions.AAIException;
36 import org.openecomp.aai.introspection.Introspector;
37 import org.openecomp.aai.introspection.Loader;
38 import org.openecomp.aai.introspection.tools.CreateUUID;
39 import org.openecomp.aai.introspection.tools.DefaultFields;
40 import org.openecomp.aai.introspection.tools.InjectKeysFromURI;
41 import org.openecomp.aai.introspection.tools.IntrospectorValidator;
42 import org.openecomp.aai.introspection.tools.Issue;
43 import org.openecomp.aai.introspection.tools.RemoveNonVisibleProperty;
44 import org.openecomp.aai.logging.ErrorLogHelper;
45 import org.openecomp.aai.logging.LoggingContext;
46 import org.openecomp.aai.util.AAIConfig;
47 import org.openecomp.aai.util.AAIConstants;
48 import org.openecomp.aai.util.AAITxnLog;
49 import org.openecomp.aai.util.FormatDate;
50
51 import com.att.eelf.configuration.EELFLogger;
52 import com.att.eelf.configuration.EELFManager;
53 import com.google.common.base.Joiner;
54
55
56 /**
57  * Base class for AAI REST API classes.
58  * Provides method to validate header information
59  * TODO should authenticate caller and authorize them for the API they are calling
60  * TODO should store the transaction
61  
62  *
63  */
64 public class RESTAPI {
65         
66         private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(RESTAPI.class);
67
68         protected final String COMPONENT = "aairest";
69
70         /**
71          * The Enum Action.
72          */
73         public enum Action {
74                 GET, PUT, POST, DELETE
75         };
76
77         
78         public AAITxnLog txn = null;
79
80         /**
81          * Gets the from app id.
82          *
83          * @param headers the headers
84          * @param logline the logline
85          * @return the from app id
86          * @throws AAIException the AAI exception
87          */
88         protected String getFromAppId(HttpHeaders headers) throws AAIException { 
89                 String fromAppId = null;
90                 if (headers != null) {
91                         List<String> fromAppIdHeader = headers.getRequestHeader("X-FromAppId");
92                         if (fromAppIdHeader != null) {
93                                 for (String fromAppIdValue : fromAppIdHeader) {
94                                         fromAppId = fromAppIdValue;
95                                 }
96                         } 
97                 }
98
99                 if (fromAppId == null) {
100                         throw new AAIException("AAI_4009");
101                 }
102
103                 LoggingContext.partnerName(fromAppId);
104
105                 return fromAppId;
106         }
107         
108         /**
109          * Gets the trans id.
110          *
111          * @param headers the headers
112          * @param logline the logline
113          * @return the trans id
114          * @throws AAIException the AAI exception
115          */
116         protected String getTransId(HttpHeaders headers) throws AAIException { 
117                 String transId = null;
118                 if (headers != null) {
119                         List<String> transIdHeader = headers.getRequestHeader("X-TransactionId");
120                         if (transIdHeader != null) {
121                                 for (String transIdValue : transIdHeader) {
122                                         transId = transIdValue;
123                                 }
124                         }
125                 }
126
127                 if (transId == null) {
128                         throw new AAIException("AAI_4010");
129                 }
130
131                 LoggingContext.requestId(transId);
132
133                 return transId;
134         }
135         
136         
137         /**
138          * Gen date.
139          *
140          * @return the string
141          */
142         protected String genDate() {
143                 FormatDate fd = new FormatDate(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT, "YYMMdd-HH:mm:ss:SSS"));
144                 
145                 return fd.getDateTime();
146         }
147
148         /**
149          * Gets the media type.
150          *
151          * @param mediaTypeList the media type list
152          * @return the media type
153          */
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;
159                         } 
160                 }
161                 return mediaType;
162         }
163         
164
165         /**
166          * Log transaction.
167          *
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
176          */
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) {        
180                 String respBuf = "";
181                 int status = 0;
182
183                 if (response != null && response.getEntity() != null) {         
184                         respBuf = response.getEntity().toString();
185                         status = response.getStatus();
186                 }
187                 logTransaction(appId, tId, action, input, rqstTm, respTm, request, respBuf, String.valueOf(status));
188         }
189         
190         /**
191          * Log transaction.
192          *
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
203          */
204         public void logTransaction(     String appId, String tId, String action, 
205                         String input, String rqstTm, String respTm, String request, String respBuf, String status) {    
206                 try {
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);
214
215                                         LOGGER.debug("HbTransId={}",hbtid);
216                                         LOGGER.debug("action={}",  action);
217                                         LOGGER.debug("urlin={}", input);
218                                 }
219
220                         }
221                 } catch (AAIException e) {
222                         // i think we do nothing
223                 }
224         }
225         
226         /* ----------helpers for common consumer actions ----------- */
227         
228         /**
229          * Sets the depth.
230          *
231          * @param depthParam the depth param
232          * @return the int
233          * @throws AAIException the AAI exception
234          */
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")){
238                         try {
239                                 depth = Integer.valueOf(depthParam);
240                         } catch (Exception e) {
241                                 throw new AAIException("AAI_4016");
242                         }
243                 }
244                 return depth;
245         }
246
247         /**
248          * Consumer exception response generator.
249          *
250          * @param headers the headers
251          * @param info the info
252          * @param templateAction the template action
253          * @param e the e
254          * @return the response
255          */
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());
261
262                 return Response
263                                 .status(e.getErrorObject().getHTTPResponseCode())
264                                 .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(headers.getAcceptableMediaTypes(), e, templateVars))
265                                 .build();
266         }
267         
268         /**
269          * Validate introspector.
270          *
271          * @param obj the obj
272          * @param loader the loader
273          * @param uri the uri
274          * @param validateRequired the validate required
275          * @throws AAIException the AAI exception
276          * @throws UnsupportedEncodingException the unsupported encoding exception
277          */
278         protected void validateIntrospector(Introspector obj, Loader loader, URI uri, HttpMethod method) throws AAIException, UnsupportedEncodingException {
279                 
280                 int maximumDepth = AAIProperties.MAXIMUM_DEPTH;
281                 boolean validateRequired = true;
282                 if (method.equals(HttpMethod.MERGE_PATCH)) {
283                         validateRequired = false;
284                         maximumDepth = 0;
285                 }
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))
293                                 .build();
294                 boolean result = validator.validate(obj);
295                 if (!result) {
296                         result = validator.resolveIssues();
297                 }
298                 if (!result) {
299                         List<String> messages = new ArrayList<>();
300                         for (Issue issue : validator.getIssues()) {
301                                 if (!issue.isResolved()) {
302                                         messages.add(issue.getDetail());
303                                 }
304                         }
305                         String errors = Joiner.on(",").join(messages);
306                         throw new AAIException("AAI_3000", errors);
307                 }
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");
315         }
316         }
317         
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;
323                 } else {
324                         type = DBConnectionType.CACHED;
325                 }
326                 
327                 return type;
328         }
329         
330         /**
331          * Gets the input media type.
332          *
333          * @param mediaType the media type
334          * @return the input media type
335          */
336         protected String getInputMediaType(MediaType mediaType) {
337                 String result = mediaType.getType() + "/" + mediaType.getSubtype();
338                 
339                 return result;
340                 
341         }
342
343 }