1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.cubby.action;
17
18 import static org.seasar.cubby.CubbyConstants.ATTR_ROUTING;
19 import static org.seasar.cubby.internal.util.LogMessages.format;
20
21 import java.io.IOException;
22 import java.lang.reflect.Method;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.regex.Pattern;
28
29 import javax.servlet.RequestDispatcher;
30 import javax.servlet.ServletException;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33
34 import org.seasar.cubby.internal.util.MetaUtils;
35 import org.seasar.cubby.internal.util.QueryStringBuilder;
36 import org.seasar.cubby.internal.util.StringUtils;
37 import org.seasar.cubby.routing.PathResolver;
38 import org.seasar.cubby.routing.Routing;
39 import org.seasar.cubby.spi.PathResolverProvider;
40 import org.seasar.cubby.spi.ProviderFactory;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
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 String path;
109
110
111 private final Routing routing;
112
113
114 private Class<?> actionClass;
115
116
117 private String methodName;
118
119
120 private Map<String, String[]> parameters;
121
122
123
124
125
126
127
128 public Forward(final String path) {
129 this.path = path;
130 this.routing = null;
131 }
132
133
134
135
136
137
138
139
140
141
142
143
144 public Forward(final Class<?> actionClass, final String methodName,
145 final Map<String, String[]> parameters) {
146 this.actionClass = actionClass;
147 this.methodName = methodName;
148 this.parameters = parameters;
149 try {
150 final Method method = actionClass.getMethod(methodName);
151 this.routing = new ForwardRouting(actionClass, method);
152 } catch (final NoSuchMethodException e) {
153 throw new IllegalArgumentException(e);
154 }
155 }
156
157
158
159
160
161
162
163
164 public Forward(final Class<?> actionClass) {
165 this(actionClass, "index");
166 }
167
168
169
170
171
172
173
174
175
176
177 public Forward(final Class<?> actionClass, final String methodName) {
178 this(actionClass, methodName, EMPTY_PARAMETERS);
179 }
180
181
182
183
184
185
186
187
188 public String getPath(final String characterEncoding) {
189 if (isReverseLookupRedirect()) {
190 final PathResolverProvider pathResolverProvider = ProviderFactory
191 .get(PathResolverProvider.class);
192 final PathResolver pathResolver = pathResolverProvider
193 .getPathResolver();
194 final String forwardPath = pathResolver.reverseLookup(actionClass,
195 methodName, parameters, characterEncoding);
196 this.path = forwardPath;
197 }
198 return this.path;
199 }
200
201
202
203
204
205
206 private boolean isReverseLookupRedirect() {
207 return this.actionClass != null && this.methodName != null
208 && this.parameters != null;
209 }
210
211
212
213
214 public void execute(final ActionContext actionContext,
215 final HttpServletRequest request, final HttpServletResponse response)
216 throws ServletException, IOException {
217 actionContext.invokePreRenderMethod();
218
219 final String forwardPath = calculateForwardPath(getPath(request
220 .getCharacterEncoding()), actionContext.getActionClass(),
221 request.getCharacterEncoding());
222 if (this.routing != null) {
223 request.setAttribute(ATTR_ROUTING, this.routing);
224 }
225 if (logger.isDebugEnabled()) {
226 logger.debug(format("DCUB0001", forwardPath, routing));
227 }
228 final RequestDispatcher dispatcher = request
229 .getRequestDispatcher(forwardPath);
230 dispatcher.forward(request, response);
231 if (logger.isDebugEnabled()) {
232 logger.debug(format("DCUB0002", forwardPath));
233 }
234
235 actionContext.invokePostRenderMethod();
236 actionContext.clearFlash();
237 }
238
239
240
241
242
243
244
245
246
247
248 protected String calculateForwardPath(final String path,
249 final Class<?> actionClass, final String characterEncoding) {
250 final String absolutePath;
251 if (getPath(characterEncoding).startsWith("/")) {
252 absolutePath = path;
253 } else {
254 final String actionDirectory = MetaUtils
255 .getActionDirectory(actionClass);
256 if (StringUtils.isEmpty(actionDirectory)) {
257 absolutePath = "/" + path;
258 } else {
259 final StringBuilder builder = new StringBuilder();
260 if (!actionDirectory.startsWith("/")) {
261 builder.append("/");
262 }
263 builder.append(actionDirectory);
264 if (!actionDirectory.endsWith("/")) {
265 builder.append("/");
266 }
267 builder.append(path);
268 absolutePath = builder.toString();
269 }
270 }
271 return absolutePath;
272 }
273
274
275
276
277
278
279
280
281
282
283 public Forward param(final String paramName, final Object paramValue) {
284 return param(paramName, new String[] { paramValue.toString() });
285 }
286
287
288
289
290
291
292
293
294
295
296 public Forward param(final String paramName, final Object[] paramValues) {
297 return param(paramName, toStringArray(paramValues));
298 }
299
300
301
302
303
304
305
306
307
308
309 public Forward param(final String paramName, final String[] paramValues) {
310 if (isReverseLookupRedirect()) {
311 if (this.parameters == EMPTY_PARAMETERS) {
312 this.parameters = new HashMap<String, String[]>();
313 }
314 this.parameters.put(paramName, paramValues);
315 } else {
316 final QueryStringBuilder builder = new QueryStringBuilder(this.path);
317 builder.addParam(paramName, paramValues);
318 this.path = builder.toString();
319 }
320 return this;
321 }
322
323
324
325
326
327
328
329
330
331
332
333 private String[] toStringArray(final Object[] paramValues) {
334 final String[] values = new String[paramValues.length];
335 for (int i = 0; i < paramValues.length; i++) {
336 values[i] = paramValues[i].toString();
337 }
338 return values;
339 }
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 }