Update SNAPSHOT to proper 1.1.0-SNAPSHOT version
[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 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;
36
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;
42 import java.net.URI;
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;
48
49
50 /**
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
55  
56  *
57  */
58 public class RESTAPI {
59         
60         private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(RESTAPI.class);
61
62         protected final String COMPONENT = "aairest";
63
64         /**
65          * The Enum Action.
66          */
67         public enum Action {
68                 GET, PUT, POST, DELETE
69         };
70
71         
72         public AAITxnLog txn = null;
73
74         /**
75          * Gets the from app id.
76          *
77          * @param headers the headers
78          * @param logline the logline
79          * @return the from app id
80          * @throws AAIException the AAI exception
81          */
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;
89                                 }
90                         } 
91                 }
92
93                 if (fromAppId == null) {
94                         throw new AAIException("AAI_4009");
95                 }
96                 
97                 return fromAppId;
98         }
99         
100         /**
101          * Gets the trans id.
102          *
103          * @param headers the headers
104          * @param logline the logline
105          * @return the trans id
106          * @throws AAIException the AAI exception
107          */
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;
115                                 }
116                         }
117                 }
118
119                 if (transId == null) {
120                         throw new AAIException("AAI_4010");
121                 }
122                 
123                 return transId;
124         }
125         
126         
127         /**
128          * Gen date.
129          *
130          * @return the string
131          */
132         protected String genDate() {
133                 Date date = new Date();
134                 DateFormat formatter = null;
135                 try {
136                         formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
137                 } catch (AAIException ex) {
138                         ErrorLogHelper.logException(ex);
139                 } finally {
140                         if (formatter == null) {
141                                 formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
142                         }
143                 }
144
145                 return formatter.format(date);
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 }