Port to java 17
[ccsdk/apps.git] / services / src / main / java / org / onap / ccsdk / apps / filters / PayloadLoggingFilter.java
1 package org.onap.ccsdk.apps.filters;
2
3 import java.io.BufferedReader;
4 import java.io.ByteArrayInputStream;
5 import java.io.CharArrayWriter;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.InputStreamReader;
9 import java.io.PrintWriter;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Collection;
13 import java.util.Enumeration;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Map.Entry;
18
19 import jakarta.servlet.Filter;
20 import jakarta.servlet.FilterChain;
21 import jakarta.servlet.FilterConfig;
22 import jakarta.servlet.ReadListener;
23 import jakarta.servlet.ServletException;
24 import jakarta.servlet.ServletInputStream;
25 import jakarta.servlet.ServletOutputStream;
26 import jakarta.servlet.ServletRequest;
27 import jakarta.servlet.ServletResponse;
28 import jakarta.servlet.WriteListener;
29 import jakarta.servlet.http.HttpServletRequest;
30 import jakarta.servlet.http.HttpServletRequestWrapper;
31 import jakarta.servlet.http.HttpServletResponse;
32 import jakarta.servlet.http.HttpServletResponseWrapper;
33
34 import org.onap.logging.filter.base.AbstractServletFilter;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.springframework.stereotype.Component;
38
39 public class PayloadLoggingFilter extends AbstractServletFilter implements Filter {
40
41         private static final Logger log = LoggerFactory.getLogger(PayloadLoggingFilter.class);
42
43         @Override
44         public void init(FilterConfig filterConfig) throws ServletException {
45         }
46
47         @Override
48         public void destroy() {
49         }
50
51         @Override
52         public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
53                 RequestWrapper req = new RequestWrapper((HttpServletRequest) request);
54                 Request requestData = req.getMessageRequest();
55                 
56                 StringBuilder requestHeaders = new StringBuilder("REQUEST|");
57             requestHeaders.append(requestData.method);
58             requestHeaders.append(":");
59             requestHeaders.append(requestData.uri);
60             requestHeaders.append("|");
61             mapstr(requestHeaders, requestData.headers);
62
63             log.info(requestHeaders.toString());
64             log.info("REQUEST BODY|{}", requestData.body);
65
66                 ResponseWrapper res = new ResponseWrapper((HttpServletResponse) response);
67
68                 chain.doFilter(req, res);
69
70                 Response responseData = res.getMessageResponse();
71                 
72                 StringBuilder responseHeaders = new StringBuilder();
73         responseHeaders.append("RESPONSE HEADERS|");
74         mapstr(responseHeaders, responseData.headers);
75         responseHeaders.append("Status:").append(responseData.code);
76         responseHeaders.append(";IsCommitted:").append(res.isCommitted());
77
78         log.info(responseHeaders.toString());
79                 log.info("RESPONSE BODY|{}", responseData.body);
80
81                 res.writeBody();
82         }
83
84         private static class Request {
85
86                 public String method;
87                 public String uri;
88                 public Map<String, Object> headers;
89                 public Map<String, Object> param;
90                 public String body;
91
92                 @Override
93                 public String toString() {
94                         StringBuilder ss = new StringBuilder();
95                         ss.append("REQUEST|").append(method).append(":").append(uri).append("|");
96                         ss.append("Headers: ");
97                         mapstr(ss, headers);
98                         if (param != null && !param.isEmpty()) {
99                                 ss.append("Parameters: ");
100                                 mapstr(ss, param);
101                         }
102                         ss.append("REQUEST BODY|\n");
103                         ss.append(body);
104                         return ss.toString();
105                 }
106         }
107
108         private static class Response {
109
110                 public int code;
111                 public String message;
112                 public Map<String, Object> headers;
113                 public String body;
114
115                 @Override
116                 public String toString() {
117                         StringBuilder ss = new StringBuilder();
118                         ss.append("HTTP Response: ").append(code).append(" ").append(message).append("\n");
119                         ss.append("Headers:\n");
120                         mapstr(ss, headers);
121                         ss.append("Body:\n");
122                         ss.append(body);
123                         return ss.toString();
124                 }
125         }
126
127         private static class RequestWrapper extends HttpServletRequestWrapper {
128
129                 private final String body;
130
131                 public RequestWrapper(HttpServletRequest request) throws IOException {
132                         super(request);
133
134                         StringBuilder stringBuilder = new StringBuilder();
135                         InputStream inputStream = request.getInputStream();
136                         if (inputStream != null) {
137                                 try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
138                                         char[] charBuffer = new char[128];
139                                         int bytesRead = -1;
140                                         while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
141                                                 stringBuilder.append(charBuffer, 0, bytesRead);
142                                         }
143                                 }
144                         }
145                         body = stringBuilder.toString();
146                 }
147
148                 @Override
149                 public ServletInputStream getInputStream() throws IOException {
150                         final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
151                         ServletInputStream servletInputStream = new ServletInputStream() {
152
153                                 @Override
154                                 public int read() throws IOException {
155                                         return byteArrayInputStream.read();
156                                 }
157
158                                 @Override
159                                 public boolean isFinished() {
160                                         return byteArrayInputStream.available() == 0;
161                                 }
162
163                                 @Override
164                                 public boolean isReady() {
165                                         return true;
166                                 }
167
168                                 @Override
169                                 public void setReadListener(ReadListener listener) {
170                                 }
171                         };
172                         return servletInputStream;
173                 }
174
175                 @Override
176                 public BufferedReader getReader() throws IOException {
177                         return new BufferedReader(new InputStreamReader(getInputStream()));
178                 }
179
180                 public String getBody() {
181                         return body;
182                 }
183
184                 public Request getMessageRequest() {
185                         Request r = new Request();
186                         r.method = getMethod();
187                         r.uri = getRequestURI();
188                         r.param = getParamMap();
189
190                         r.headers = new HashMap<>();
191                         Enumeration<String> headerNames = getHeaderNames();
192                         while (headerNames.hasMoreElements()) {
193                                 String name = headerNames.nextElement();
194
195                                 if (name.equalsIgnoreCase("authorization")) {
196                                         r.headers.put(name, "***REDACTED***");
197                                         continue;
198                                 }
199
200                                 Enumeration<String> values = getHeaders(name);
201                                 List<String> valueList = new ArrayList<>();
202                                 while (values.hasMoreElements()) {
203                                         valueList.add(values.nextElement());
204                                 }
205                                 if (valueList.size() > 1) {
206                                         r.headers.put(name, valueList);
207                                 } else if (valueList.size() > 0) {
208                                         r.headers.put(name, valueList.get(0));
209                                 }
210                         }
211
212                         r.body = getBody();
213
214                         return r;
215                 }
216
217                 private Map<String, Object> getParamMap() {
218                         Map<String, String[]> parameterMap = getParameterMap();
219                         Map<String, Object> paramMap = new HashMap<>();
220                         if (parameterMap != null) {
221                                 for (Entry<String, String[]> entry : parameterMap.entrySet()) {
222                                         String name = entry.getKey();
223                                         String[] values = entry.getValue();
224                                         if (values != null && values.length > 0) {
225                                                 if (values.length == 1) {
226                                                         paramMap.put(name, values[0]);
227                                                 } else {
228                                                         paramMap.put(name, Arrays.<String> asList(values));
229                                                 }
230                                         }
231                                 }
232                         }
233                         return paramMap;
234                 }
235         }
236
237         public class ResponseWrapper extends HttpServletResponseWrapper {
238
239                 private CharArrayWriter writer = new CharArrayWriter();
240
241                 private String statusMessage;
242
243                 public ResponseWrapper(HttpServletResponse response) {
244                         super(response);
245                 }
246
247                 @Override
248                 public PrintWriter getWriter() {
249                         return new PrintWriter(writer);
250                 }
251
252                 @Override
253                 public ServletOutputStream getOutputStream() {
254                         return new ServletOutputStream() {
255
256                                 @Override
257                                 public void write(int b) throws IOException {
258                                         writer.write(b);
259                                 }
260
261                                 @Override
262                                 public void setWriteListener(WriteListener listener) {
263                                 }
264
265                                 @Override
266                                 public boolean isReady() {
267                                         return true;
268                                 }
269                         };
270                 }
271
272                 @SuppressWarnings("deprecation")
273                 @Override
274                 public void setStatus(int sc) {
275                         super.setStatus(sc);
276                 }
277
278                 public Response getMessageResponse() {
279                         Response r = new Response();
280                         r.code = getStatus();
281                         r.message = statusMessage == null ? "" : statusMessage;
282
283                         r.headers = new HashMap<>();
284                         Collection<String> headerNames = getHeaderNames();
285                         for (String name : headerNames) {
286
287                                 if (name.equalsIgnoreCase("authorization")) {
288                                         r.headers.put(name, "***REDACTED***");
289                                         continue;
290                                 }
291
292                                 Collection<String> values = getHeaders(name);
293                                 List<String> valueList = new ArrayList<>(values);
294                                 if (valueList.size() > 1) {
295                                         r.headers.put(name, valueList);
296                                 } else {
297                                         r.headers.put(name, valueList.get(0));
298                                 }
299                         }
300
301                         r.body = writer.toString();
302
303                         return r;
304                 }
305
306                 public void writeBody() throws IOException {
307                         String body = writer.toString();
308                         setContentLength(body.length());
309                         super.getWriter().write(body);
310                 }
311         }
312
313         private static void mapstr(StringBuilder ss, Map<String, Object> m) {
314                 if (m != null) {
315                         for (Entry<String, Object> entry : m.entrySet()) {
316                                 ss.append(entry.getKey()).append(": ").append(entry.getValue()).append(";");
317                         }
318                 }
319         }
320 }