1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.gateway.kernel.rest;
21
22 import com.fasterxml.jackson.databind.node.ArrayNode;
23 import io.netty.buffer.ByteBuf;
24 import io.netty.buffer.Unpooled;
25 import io.netty.channel.ChannelFuture;
26 import io.netty.channel.ChannelHandlerContext;
27 import io.netty.handler.codec.http.HttpHeaderNames;
28 import io.netty.handler.codec.http.HttpResponse;
29 import io.netty.handler.codec.http.HttpResponseStatus;
30 import io.netty.handler.codec.http.multipart.FileUpload;
31 import org.waarp.common.logging.SysErrLogger;
32 import org.waarp.common.logging.WaarpLogger;
33 import org.waarp.common.logging.WaarpLoggerFactory;
34 import org.waarp.common.utility.WaarpStringUtils;
35 import org.waarp.gateway.kernel.exception.HttpForbiddenRequestException;
36 import org.waarp.gateway.kernel.exception.HttpIncorrectRequestException;
37 import org.waarp.gateway.kernel.exception.HttpInvalidAuthenticationException;
38 import org.waarp.gateway.kernel.exception.HttpMethodNotAllowedRequestException;
39 import org.waarp.gateway.kernel.exception.HttpNotFoundRequestException;
40 import org.waarp.gateway.kernel.rest.DataModelRestMethodHandler.COMMAND_TYPE;
41 import org.waarp.gateway.kernel.rest.HttpRestHandler.METHOD;
42
43 import java.util.Collections;
44 import java.util.HashSet;
45 import java.util.Set;
46
47
48
49
50 public abstract class RestMethodHandler {
51
52
53
54 private static final WaarpLogger logger =
55 WaarpLoggerFactory.getLogger(RestMethodHandler.class);
56 private static final METHOD[] METHOD_0_LENGTH = new METHOD[0];
57
58 protected final String name;
59 protected final String path;
60 protected final Set<METHOD> methods;
61 protected final boolean isBodyJsonDecode;
62 protected final RestConfiguration restConfiguration;
63
64
65
66
67
68
69
70
71
72
73
74
75 protected RestMethodHandler(final String name, final String path,
76 final boolean isBodyJsonDecode,
77 final RestConfiguration config,
78 final METHOD... method) {
79 this.name = name;
80 this.path = path;
81 methods = new HashSet<HttpRestHandler.METHOD>();
82 setMethods(method);
83 setMethods(METHOD.OPTIONS);
84 this.isBodyJsonDecode = isBodyJsonDecode;
85 restConfiguration = config;
86 }
87
88 protected final void setMethods(final METHOD... method) {
89 Collections.addAll(methods, method);
90 }
91
92
93
94
95
96
97
98 protected final void setIntersectionMethods(final METHOD[] selectedMethods,
99 final METHOD... validMethod) {
100 final Set<METHOD> set = new HashSet<METHOD>();
101 Collections.addAll(set, validMethod);
102 final Set<METHOD> set2 = new HashSet<METHOD>();
103 Collections.addAll(set2, selectedMethods);
104 set.retainAll(set2);
105 final METHOD[] methodsToSet = set.toArray(METHOD_0_LENGTH);
106 setMethods(methodsToSet);
107 }
108
109 public final String getName() {
110 return name;
111 }
112
113 public final String getPath() {
114 return path;
115 }
116
117
118
119
120
121
122 public final boolean isMethodIncluded(final METHOD method) {
123 return methods.contains(method);
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138 public abstract void checkHandlerSessionCorrectness(HttpRestHandler handler,
139 RestArgument arguments,
140 RestArgument result)
141 throws HttpForbiddenRequestException;
142
143
144
145
146
147
148
149
150
151
152
153 public abstract void getFileUpload(HttpRestHandler handler, FileUpload data,
154 RestArgument arguments,
155 RestArgument result)
156 throws HttpIncorrectRequestException;
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public abstract Object getBody(HttpRestHandler handler, ByteBuf body,
171 RestArgument arguments, RestArgument result)
172 throws HttpIncorrectRequestException;
173
174
175
176
177
178
179
180
181
182
183
184
185 public abstract void endParsingRequest(HttpRestHandler handler,
186 RestArgument arguments,
187 RestArgument result, Object body)
188 throws HttpIncorrectRequestException, HttpInvalidAuthenticationException,
189 HttpNotFoundRequestException;
190
191
192
193
194
195
196
197
198
199
200
201
202 public HttpResponseStatus handleException(final HttpRestHandler handler,
203 final RestArgument arguments,
204 final RestArgument result,
205 final Object body,
206 final Exception exception) {
207 if (exception instanceof HttpInvalidAuthenticationException) {
208 result.setResult(HttpResponseStatus.UNAUTHORIZED);
209 return HttpResponseStatus.UNAUTHORIZED;
210 } else if (exception instanceof HttpForbiddenRequestException) {
211 result.setResult(HttpResponseStatus.FORBIDDEN);
212 return HttpResponseStatus.FORBIDDEN;
213 } else if (exception instanceof HttpIncorrectRequestException) {
214 result.setResult(HttpResponseStatus.BAD_REQUEST);
215 return HttpResponseStatus.BAD_REQUEST;
216 } else if (exception instanceof HttpMethodNotAllowedRequestException) {
217 result.setResult(HttpResponseStatus.METHOD_NOT_ALLOWED);
218 return HttpResponseStatus.METHOD_NOT_ALLOWED;
219 } else if (exception instanceof HttpNotFoundRequestException) {
220 result.setResult(HttpResponseStatus.NOT_FOUND);
221 return HttpResponseStatus.NOT_FOUND;
222 } else {
223 result.setResult(HttpResponseStatus.INTERNAL_SERVER_ERROR);
224 return HttpResponseStatus.INTERNAL_SERVER_ERROR;
225 }
226 }
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 public abstract ChannelFuture sendResponse(HttpRestHandler handler,
242 ChannelHandlerContext ctx,
243 RestArgument arguments,
244 RestArgument result, Object body,
245 HttpResponseStatus status);
246
247 protected final ChannelFuture sendOptionsResponse(
248 final HttpRestHandler handler, final ChannelHandlerContext ctx,
249 final RestArgument result, final HttpResponseStatus status) {
250 final String list = result.getAllowOption();
251 final String answer = result.toString();
252 final ByteBuf buffer =
253 Unpooled.wrappedBuffer(answer.getBytes(WaarpStringUtils.UTF8));
254 final HttpResponse response = handler.getResponse(buffer);
255 if (status == HttpResponseStatus.UNAUTHORIZED) {
256 return ctx.writeAndFlush(response);
257 }
258 response.headers().add(HttpHeaderNames.CONTENT_TYPE, "application/json");
259 response.headers().add(HttpHeaderNames.REFERER, handler.getRequest().uri());
260 response.headers().add(HttpHeaderNames.ALLOW, list);
261 logger.debug("Msg ready");
262 final ChannelFuture future = ctx.writeAndFlush(response);
263 if (handler.isWillClose()) {
264 SysErrLogger.FAKE_LOGGER.sysout(
265 "Will close session in RestMethodHandler");
266 return future;
267 }
268 return null;
269 }
270
271
272
273
274
275
276
277
278 protected void optionsCommand(final HttpRestHandler handler,
279 final RestArgument arguments,
280 final RestArgument result) {
281 result.setCommand(COMMAND_TYPE.OPTIONS);
282 final METHOD[] realmethods = METHOD.values();
283 final boolean[] allMethods = new boolean[realmethods.length];
284 for (final METHOD methoditem : methods) {
285 allMethods[methoditem.ordinal()] = true;
286 }
287 StringBuilder allow = null;
288 for (int i = 0; i < allMethods.length; i++) {
289 if (allMethods[i]) {
290 if (allow == null) {
291 allow = new StringBuilder(realmethods[i].name());
292 } else {
293 allow.append(',').append(realmethods[i].name());
294 }
295 }
296 }
297 if (allow != null) {
298 result.addOptions(allow.toString(), path, getDetailedAllow());
299 }
300 }
301
302
303
304
305 protected abstract ArrayNode getDetailedAllow();
306
307
308
309
310 public final boolean isBodyJsonDecoded() {
311 return isBodyJsonDecode;
312 }
313 }