1 package common.http.interceptor;
2
3 import javax.servlet.ServletException;
4 import javax.servlet.ServletRequest;
5 import javax.servlet.ServletResponse;
6 import javax.servlet.http.HttpServlet;
7 import javax.servlet.http.HttpServletRequest;
8 import javax.servlet.http.HttpServletResponse;
9 import java.io.IOException;
10 import java.lang.reflect.Method;
11 import java.util.Arrays;
12 import java.util.Comparator;
13 import java.util.Map;
14 import java.util.Objects;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.stream.Stream;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public abstract class InterceptableServlet extends HttpServlet {
47 private static final Map<String, String> methods =
48 Map.of(
49 "GET", "doGet",
50 "POST", "doPost",
51 "PUT", "doPut",
52 "TRACE", "doTrace",
53 "OPTIONS", "doOptions",
54 "DELETE", "doDelete",
55 "HEAD", "doHead"
56 );
57
58 private final Map<String, HttpServletBiConsumer> chains = new ConcurrentHashMap<>();
59
60 private ServletInterceptor<?>[] getInterceptors(String httpMethodName) {
61 String javaMethodName = methods.get(httpMethodName);
62 if(javaMethodName == null){
63
64 throw new IllegalArgumentException();
65 }
66
67 Method method;
68 try {
69 method = this.getClass()
70 .getDeclaredMethod(javaMethodName, HttpServletRequest.class, HttpServletResponse.class);
71 } catch (NoSuchMethodException e) {
72
73
74 return new ServletInterceptor[]{};
75 }
76
77
78
79 return Stream.concat(Arrays.stream(getClass().getAnnotations()), Arrays.stream(method.getAnnotations()))
80 .map(ServletInterceptorFactory::instantiate)
81 .filter(Objects::nonNull)
82 .sorted(Comparator.comparingInt(ServletInterceptor::priority))
83 .toArray(ServletInterceptor[]::new);
84 }
85
86 private HttpServletBiConsumer buildChain(ServletInterceptor<?>[] interceptors, HttpServletBiConsumer target){
87
88
89 HttpServletBiConsumer current = target;
90 for(int i = interceptors.length-1; i >= 0; i--){
91 ServletInterceptor<?> interceptor = interceptors[i];
92
93 HttpServletBiConsumer next = current;
94 current = (req, res) -> interceptor.handle(req, res, next);
95 }
96 return current;
97 }
98
99
100 private void superService(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
101 super.service(req, resp);
102 }
103
104 @Override
105 protected final void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
106 String httpMethod = req.getMethod();
107 chains.computeIfAbsent(httpMethod, key -> buildChain(getInterceptors(key), this::superService)).handle(req,resp);
108 }
109
110 @Override
111 public final void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
112 service((HttpServletRequest) req, (HttpServletResponse) res);
113 }
114
115 }