Added oparent to sdc main
[sdc.git] / openecomp-be / lib / openecomp-sdc-logging-lib / openecomp-sdc-logging-spring / src / main / java / org / openecomp / sdc / logging / servlet / spring / LoggingInterceptor.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.logging.servlet.spring;
18
19 import static org.openecomp.sdc.logging.api.StatusCode.COMPLETE;
20 import static org.openecomp.sdc.logging.api.StatusCode.ERROR;
21 import static org.springframework.http.HttpStatus.Series.REDIRECTION;
22 import static org.springframework.http.HttpStatus.Series.SUCCESSFUL;
23
24 import java.util.Objects;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27 import org.openecomp.sdc.logging.api.Logger;
28 import org.openecomp.sdc.logging.api.LoggerFactory;
29 import org.openecomp.sdc.logging.api.StatusCode;
30 import org.openecomp.sdc.logging.servlet.AuditTracker;
31 import org.openecomp.sdc.logging.servlet.CombinedTracker;
32 import org.openecomp.sdc.logging.servlet.ContextTracker;
33 import org.openecomp.sdc.logging.servlet.HttpHeader;
34 import org.openecomp.sdc.logging.servlet.RequestProcessingResult;
35 import org.openecomp.sdc.logging.servlet.Tracker;
36 import org.springframework.http.HttpStatus;
37 import org.springframework.stereotype.Component;
38 import org.springframework.web.method.HandlerMethod;
39 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
40
41 /**
42  * <p><b>IMPORTANT</b>: For this interceptor to work, all exceptions must be properly handled before being returned to a
43  * client. Any unexpected, automatically handled exception bypasses the interceptor and will not be logged.</p>
44  * <p>The interceptor must be either registered in Spring configuration XML as a bean, or programmatically as described
45  * in <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-config-interceptors">
46  * Spring MVC Config: Interceptors</a>.</p>
47  *
48  * @author evitaliy
49  * @since 02 Aug 2018
50  */
51 @Component
52 public class LoggingInterceptor extends HandlerInterceptorAdapter {
53
54     static final String LOGGING_TRACKER_KEY = "onap.logging.tracker";
55
56     private static final Logger LOGGER = LoggerFactory.getLogger(LoggingInterceptor.class);
57
58     private final HttpHeader partnerNameHeader;
59     private final HttpHeader requestIdHeader;
60
61     public LoggingInterceptor(HttpHeader partnerNameHeader, HttpHeader requestIdHeader) {
62         this.partnerNameHeader = Objects.requireNonNull(partnerNameHeader);
63         this.requestIdHeader = Objects.requireNonNull(requestIdHeader);
64     }
65
66     @Override
67     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
68         Class<?> resourceClass = getResourceType(handler);
69         Tracker tracker = new CombinedTracker(
70                 new ContextTracker(partnerNameHeader, requestIdHeader),
71                 new AuditTracker(resourceClass));
72         request.setAttribute(LOGGING_TRACKER_KEY, tracker);
73         tracker.preRequest(request);
74         return true;
75     }
76
77     @Override
78     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
79             Exception ex) {
80
81         Tracker tracker = (Tracker) request.getAttribute(LOGGING_TRACKER_KEY);
82
83         if (tracker == null) {
84             LOGGER.debug("No logging tracker received");
85             return;
86         }
87
88         tracker.postRequest(new ServletResponseResult(response.getStatus()));
89     }
90
91     private Class<?> getResourceType(Object handler) {
92
93         if (handler instanceof HandlerMethod) {
94             return ((HandlerMethod) handler).getMethod().getDeclaringClass();
95         }
96
97         return LoggingInterceptor.class;
98     }
99
100     static class ServletResponseResult implements RequestProcessingResult {
101
102         private final StatusInfo statusInfo;
103
104         ServletResponseResult(int status) {
105             this.statusInfo = init(status);
106         }
107
108         private StatusInfo init(int status) {
109
110             try {
111                 return new StatusInfo(HttpStatus.valueOf(status));
112             } catch (IllegalArgumentException e) {
113                 return new StatusInfo(status, "Non-standard HTTP status", HttpStatus.Series.valueOf(status));
114             }
115         }
116
117         @Override
118         public int getStatus() {
119             return statusInfo.getStatus();
120         }
121
122         @Override
123         public StatusCode getStatusCode() {
124             return statusInfo.getStatusCode();
125         }
126
127         @Override
128         public String getStatusPhrase() {
129             return statusInfo.getReasonPhrase();
130         }
131     }
132
133     private static class StatusInfo {
134
135         private final int status;
136         private final String reasonPhrase;
137         private final HttpStatus.Series series;
138
139         private StatusInfo(HttpStatus httpStatus) {
140             this(httpStatus.value(), httpStatus.getReasonPhrase(), httpStatus.series());
141         }
142
143         private StatusInfo(int status, String reasonPhrase, HttpStatus.Series series) {
144             this.status = status;
145             this.reasonPhrase = reasonPhrase;
146             this.series = series;
147         }
148
149         private int getStatus() {
150             return status;
151         }
152
153         private String getReasonPhrase() {
154             return reasonPhrase;
155         }
156
157         private StatusCode getStatusCode() {
158             return series.equals(SUCCESSFUL) || series.equals(REDIRECTION) ? COMPLETE : ERROR;
159         }
160     }
161 }