Upgrade SDC from Titan to Janus Graph
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / filters / BeServletFilter.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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.sdc.be.filters;
22
23 import com.google.gson.GsonBuilder;
24 import org.openecomp.sdc.be.config.BeEcompErrorManager;
25 import org.openecomp.sdc.be.config.Configuration;
26 import org.openecomp.sdc.be.config.ConfigurationManager;
27 import org.openecomp.sdc.be.dao.api.ActionStatus;
28 import org.openecomp.sdc.be.dao.jsongraph.HealingJanusGraphDao;
29 import org.openecomp.sdc.be.impl.ComponentsUtils;
30 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
31 import org.openecomp.sdc.common.api.Constants;
32 import org.openecomp.sdc.common.log.elements.LogFieldsMdcHandler;
33 import org.openecomp.sdc.common.log.enums.LogLevel;
34 import org.openecomp.sdc.common.log.enums.Severity;
35 import org.openecomp.sdc.common.log.wrappers.Logger;
36 import org.openecomp.sdc.common.log.wrappers.LoggerSdcAudit;
37 import org.openecomp.sdc.common.util.ThreadLocalsHolder;
38 import org.openecomp.sdc.exception.ResponseFormat;
39 import org.slf4j.MDC;
40 import org.springframework.web.context.WebApplicationContext;
41
42 import javax.annotation.Priority;
43 import javax.servlet.ServletContext;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.ws.rs.container.ContainerRequestContext;
46 import javax.ws.rs.container.ContainerRequestFilter;
47 import javax.ws.rs.container.ContainerResponseContext;
48 import javax.ws.rs.container.ContainerResponseFilter;
49 import javax.ws.rs.core.Context;
50 import javax.ws.rs.core.Response;
51 import javax.ws.rs.ext.Provider;
52 import java.io.IOException;
53 import java.util.UUID;
54
55 @Provider
56 @Priority(1)
57 public class BeServletFilter implements ContainerRequestFilter, ContainerResponseFilter {
58
59     @Context
60     private HttpServletRequest sr;
61     private static final Logger log = Logger.getLogger(BeServletFilter.class);
62     private static LoggerSdcAudit audit = new LoggerSdcAudit(BeServletFilter.class);
63
64     @Override
65     public void filter(ContainerRequestContext requestContext) throws IOException {
66         try {
67
68             MDC.clear();
69
70             audit.startLog(requestContext);
71
72             // In case of 405 response code, this function is not entered, then
73             // we'll process
74             // the MDC fields and UUID during the response
75             ThreadLocalsHolder.setMdcProcessed(true);
76
77             // Timing HTTP request
78             ThreadLocalsHolder.setRequestStartTime(System.currentTimeMillis());
79
80             String uuid = processMdcFields(requestContext);
81
82             ThreadLocalsHolder.setUuid(uuid);
83
84             inHttpRequest();
85
86         } catch (Exception e) {
87             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Error during request filter");
88             log.debug("Error during request filter: {} ", e);
89         }
90     }
91
92     @Override
93     public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
94         try {
95             // Formatting the response in case of 405
96             if (responseContext.getStatus() == Response.Status.METHOD_NOT_ALLOWED.getStatusCode()) {
97                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_ALLOWED);
98                 responseContext.setEntity(new GsonBuilder().setPrettyPrinting().create().toJson(responseFormat.getRequestError()));
99             }
100
101             if (ThreadLocalsHolder.isMdcProcessed()) {
102                 // filter() was executed during request - this is the regular
103                 // flow
104                 responseContext.getHeaders().add(Constants.X_ECOMP_REQUEST_ID_HEADER, ThreadLocalsHolder.getUuid());
105                 Long startTime = ThreadLocalsHolder.getRequestStartTime();
106                 if (startTime != null) {
107                     long endTime = System.currentTimeMillis();
108                     MDC.put("timer", Long.toString(endTime - startTime));
109                 }
110             } else {
111                 // this is the 405 response code case
112                 // we have no MDC fields since filter() wasn't executed during
113                 // request
114                 String uuid = processMdcFields(requestContext);
115
116                 responseContext.getHeaders().add(Constants.X_ECOMP_REQUEST_ID_HEADER, uuid);
117                 // call to start-log method to fill mandatory fields
118                 audit.startLog(requestContext);
119             }
120
121             writeToJanusGraph(responseContext);
122
123             //write to Audit log in case it's valuable action
124             // (e.g. ignoring healthCheck and any other unlogged urls as in yaml
125             if (isInfoLog()) {
126                 audit.log(sr.getRemoteAddr(),
127                         requestContext,
128                         responseContext.getStatusInfo(),
129                         LogLevel.INFO,
130                         Severity.OK,
131                         LogFieldsMdcHandler.getInstance()
132                                 .getAuditMessage());
133             }
134
135             outHttpResponse(responseContext);
136
137         } catch (Exception e) {
138             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Error during request filter");
139             log.debug("Error during response filter: {} ", e);
140         } finally {
141             // Cleaning up
142             MDC.clear();
143             ThreadLocalsHolder.cleanup();
144         }
145     }
146
147     private void writeToJanusGraph(ContainerResponseContext responseContext) {
148         log.debug("Close transaction from filter");
149         HealingJanusGraphDao janusGraphDao = getJanusGraphDao();
150         if (janusGraphDao != null) {
151             int status = responseContext.getStatus();
152             if (status == Response.Status.OK.getStatusCode() ||
153                     status == Response.Status.CREATED.getStatusCode() ||
154                     status == Response.Status.NO_CONTENT.getStatusCode()) {
155                 janusGraphDao.commit();
156                 log.debug("Doing commit from filter");
157             } else {
158                 janusGraphDao.rollback();
159                 log.debug("Doing rollback from filter");
160             }
161         }
162     }
163
164     private String processMdcFields(ContainerRequestContext requestContext) {
165         // UserId for logging
166         String userId = requestContext.getHeaderString(Constants.USER_ID_HEADER);
167         MDC.put("userId", userId);
168
169         String serviceInstanceID = requestContext.getHeaderString(Constants.X_ECOMP_SERVICE_ID_HEADER);
170         MDC.put("serviceInstanceID", serviceInstanceID);
171
172         MDC.put("remoteAddr", sr.getRemoteAddr());
173         MDC.put("localAddr", sr.getLocalAddr());
174
175         // UUID
176         String uuid = requestContext.getHeaderString(Constants.X_ECOMP_REQUEST_ID_HEADER);
177         if (uuid == null) {
178             // Generate the UUID
179             uuid = UUID.randomUUID().toString();
180
181             // Add to MDC for logging
182             MDC.put("uuid", uuid);
183
184             // This log message should already be with the UUID
185             uuidGeneration(uuid);
186
187         } else {
188             // According to Ella, in case this header exists, we don't have to
189             // perform any validations
190             // since it's not our responsibilty, so we log the UUID just as it
191             // was received.
192             MDC.put("uuid", uuid);
193         }
194         return uuid;
195     }
196
197     private ComponentsUtils getComponentsUtils() {
198         ServletContext context = this.sr.getSession().getServletContext();
199
200         WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
201         WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
202         return webApplicationContext.getBean(ComponentsUtils.class);
203     }
204
205     private HealingJanusGraphDao getJanusGraphDao() {
206         ServletContext context = this.sr.getSession().getServletContext();
207
208         WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
209         WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
210         return webApplicationContext.getBean(HealingJanusGraphDao.class);
211     }
212
213     // Extracted for purpose of clear method name, for logback %M parameter
214     private void inHttpRequest() {
215         if (isInfoLog()) {
216             log.info("{} {} {}", sr.getMethod(), sr.getRequestURI(), sr.getProtocol());
217         } else {
218             log.debug("{} {} {}", sr.getMethod(), sr.getRequestURI(), sr.getProtocol());
219         }
220     }
221
222     // Extracted for purpose of clear method name, for logback %M parameter
223     private void outHttpResponse(ContainerResponseContext responseContext) {
224         if (isInfoLog()) {
225             log.info("{} {} {} SC=\"{}\"", sr.getMethod(), sr.getRequestURI(), sr.getProtocol(), responseContext.getStatus());
226         } else {
227             log.debug("{} {} {} SC=\"{}\"", sr.getMethod(), sr.getRequestURI(), sr.getProtocol(), responseContext.getStatus());
228         }
229     }
230
231     private boolean isInfoLog() {
232         boolean logRequest = true;
233         Configuration configuration = ConfigurationManager.getConfigurationManager().getConfiguration();
234         String requestURI = sr.getRequestURI();
235         if (requestURI != null && configuration.getUnLoggedUrls() != null) {
236             logRequest = !configuration.getUnLoggedUrls().contains(requestURI);
237         }
238         return logRequest;
239     }
240
241     // Extracted for purpose of clear method name, for logback %M parameter
242     private void uuidGeneration(String uuid) {
243         log.info("No requestID  provided -> Generated UUID {}", uuid);
244     }
245 }