1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.seasar.cubby.action;
18
19 import static org.seasar.cubby.CubbyConstants.ATTR_ROUTING;
20 import static org.seasar.cubby.internal.util.LogMessages.format;
21
22 import java.io.IOException;
23 import java.lang.reflect.Method;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.regex.Pattern;
29
30 import javax.servlet.RequestDispatcher;
31 import javax.servlet.ServletException;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpServletResponse;
34
35 import org.seasar.cubby.internal.util.MetaUtils;
36 import org.seasar.cubby.internal.util.QueryStringBuilder;
37 import org.seasar.cubby.internal.util.StringUtils;
38 import org.seasar.cubby.routing.PathResolver;
39 import org.seasar.cubby.routing.Routing;
40 import org.seasar.cubby.spi.PathResolverProvider;
41 import org.seasar.cubby.spi.ProviderFactory;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 public class Forward implements ActionResult {
99
100
101 private static final Logger logger = LoggerFactory.getLogger(Forward.class);
102
103
104 private static final Map<String, String[]> EMPTY_PARAMETERS = Collections
105 .emptyMap();
106
107
108 private final PathResolverProvider pathResolverProvider;
109
110
111 private String path;
112
113
114 private final Routing routing;
115
116
117 private Class<?> actionClass;
118
119
120 private String methodName;
121
122
123 private Map<String, String[]> parameters;
124
125
126
127
128
129
130
131 public Forward(final String path) {
132 this.pathResolverProvider = null;
133 this.path = path;
134 this.routing = null;
135 }
136
137
138
139
140
141
142
143
144
145
146
147 public Forward(final Class<?> actionClass, final String methodName,
148 final Map<String, String[]> parameters) {
149 this.pathResolverProvider = ProviderFactory
150 .get(PathResolverProvider.class);
151 this.actionClass = actionClass;
152 this.methodName = methodName;
153 this.parameters = parameters;
154 try {
155 final Method method = actionClass.getMethod(methodName);
156 this.routing = new ForwardRouting(actionClass, method);
157 } catch (final NoSuchMethodException e) {
158 throw new IllegalArgumentException(e);
159 }
160 }
161
162
163
164
165
166
167
168 public Forward(final Class<?> actionClass) {
169 this(actionClass, "index");
170 }
171
172
173
174
175
176
177
178
179
180 public Forward(final Class<?> actionClass, final String methodName) {
181 this(actionClass, methodName, EMPTY_PARAMETERS);
182 }
183
184
185
186
187
188
189
190
191 public String getPath(final String characterEncoding) {
192 if (isReverseLookupRedirect()) {
193 final PathResolver pathResolver = this.pathResolverProvider
194 .getPathResolver();
195 final String forwardPath = pathResolver.reverseLookup(actionClass,
196 methodName, parameters, characterEncoding);
197 this.path = forwardPath;
198 }
199 return this.path;
200 }
201
202
203
204
205
206
207 private boolean isReverseLookupRedirect() {
208 return this.actionClass != null && this.methodName != null
209 && this.parameters != null;
210 }
211
212
213
214
215 public void execute(final ActionContext actionContext,
216 final HttpServletRequest request, final HttpServletResponse response)
217 throws ServletException, IOException {
218 actionContext.invokePreRenderMethod();
219
220 final String forwardPath = calculateForwardPath(getPath(request
221 .getCharacterEncoding()), actionContext.getActionClass(),
222 request.getCharacterEncoding());
223 if (this.routing != null) {
224 request.setAttribute(ATTR_ROUTING, this.routing);
225 }
226 if (logger.isDebugEnabled()) {
227 logger.debug(format("DCUB0001", forwardPath, routing));
228 }
229 final RequestDispatcher dispatcher = request
230 .getRequestDispatcher(forwardPath);
231 dispatcher.forward(request, response);
232 if (logger.isDebugEnabled()) {
233 logger.debug(format("DCUB0002", forwardPath));
234 }
235
236 actionContext.invokePostRenderMethod();
237 actionContext.clearFlash();
238 }
239
240
241
242
243
244
245
246
247
248
249 protected String calculateForwardPath(final String path,
250 final Class<?> actionClass, final String characterEncoding) {
251 final String absolutePath;
252 if (getPath(characterEncoding).startsWith("/")) {
253 absolutePath = path;
254 } else {
255 final String actionDirectory = MetaUtils
256 .getActionDirectory(actionClass);
257 if (StringUtils.isEmpty(actionDirectory)) {
258 absolutePath = "/" + path;
259 } else {
260 final StringBuilder builder = new StringBuilder();
261 if (!actionDirectory.startsWith("/")) {
262 builder.append("/");
263 }
264 builder.append(actionDirectory);
265 if (!actionDirectory.endsWith("/")) {
266 builder.append("/");
267 }
268 builder.append(path);
269 absolutePath = builder.toString();
270 }
271 }
272 return absolutePath;
273 }
274
275
276
277
278
279
280
281
282
283
284 public Forward param(final String paramName, final Object paramValue) {
285 return param(paramName, new String[] { paramValue.toString() });
286 }
287
288
289
290
291
292
293
294
295
296
297 public Forward param(final String paramName, final Object[] paramValues) {
298 return param(paramName, toStringArray(paramValues));
299 }
300
301
302
303
304
305
306
307
308
309
310 public Forward param(final String paramName, final String[] paramValues) {
311 if (isReverseLookupRedirect()) {
312 if (this.parameters == EMPTY_PARAMETERS) {
313 this.parameters = new HashMap<String, String[]>();
314 }
315 this.parameters.put(paramName, paramValues);
316 } else {
317 final QueryStringBuilder builder = new QueryStringBuilder(this.path);
318 builder.addParam(paramName, paramValues);
319 this.path = builder.toString();
320 }
321 return this;
322 }
323
324
325
326
327
328
329
330
331
332
333
334 private String[] toStringArray(final Object[] paramValues) {
335 final String[] values = new String[paramValues.length];
336 for (int i = 0; i < paramValues.length; i++) {
337 values[i] = paramValues[i].toString();
338 }
339 return values;
340 }
341
342
343
344
345
346
347 private static class ForwardRouting implements Routing {
348
349
350 private final Class<?> actionClass;
351
352
353 private final Method actionMethod;
354
355
356
357
358 private ForwardRouting(final Class<?> actionClass,
359 final Method actionMethod) {
360 this.actionClass = actionClass;
361 this.actionMethod = actionMethod;
362 }
363
364
365
366
367 public Class<?> getActionClass() {
368 return actionClass;
369 }
370
371
372
373
374 public Method getActionMethod() {
375 return actionMethod;
376 }
377
378
379
380
381 public String getActionPath() {
382 return null;
383 }
384
385
386
387
388 public List<String> getUriParameterNames() {
389 return null;
390 }
391
392
393
394
395 public Pattern getPattern() {
396 return null;
397 }
398
399
400
401
402 public RequestMethod getRequestMethod() {
403 return null;
404 }
405
406
407
408
409 public String getOnSubmit() {
410 return null;
411 }
412
413
414
415
416 public int getPriority() {
417 return 0;
418 }
419
420
421
422
423 public boolean isAcceptable(final String requestMethod) {
424 return true;
425 }
426
427
428
429
430 @Override
431 public String toString() {
432 return new StringBuilder().append("[").append(actionMethod).append(
433 "]").toString();
434 }
435
436 }
437
438 }