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 public class Forward implements ActionResult {
98
99
100 private static final Logger logger = LoggerFactory.getLogger(Forward.class);
101
102
103 private static final Map<String, String[]> EMPTY_PARAMETERS = Collections
104 .emptyMap();
105
106
107 private final PathResolverProvider pathResolverProvider;
108
109
110 private String path;
111
112
113 private final Routing routing;
114
115
116 private Class<?> actionClass;
117
118
119 private String methodName;
120
121
122 private Map<String, String[]> parameters;
123
124
125
126
127
128
129
130 public Forward(final String path) {
131 this.pathResolverProvider = null;
132 this.path = path;
133 this.routing = null;
134 }
135
136
137
138
139
140
141
142
143
144
145
146 public Forward(final Class<?> actionClass, final String methodName,
147 final Map<String, String[]> parameters) {
148 this.pathResolverProvider = ProviderFactory
149 .get(PathResolverProvider.class);
150 this.actionClass = actionClass;
151 this.methodName = methodName;
152 this.parameters = parameters;
153 try {
154 final Method method = actionClass.getMethod(methodName);
155 this.routing = new ForwardRouting(actionClass, method);
156 } catch (final NoSuchMethodException e) {
157 throw new IllegalArgumentException(e);
158 }
159 }
160
161
162
163
164
165
166
167 public Forward(final Class<?> actionClass) {
168 this(actionClass, "index");
169 }
170
171
172
173
174
175
176
177
178
179 public Forward(final Class<?> actionClass, final String methodName) {
180 this(actionClass, methodName, EMPTY_PARAMETERS);
181 }
182
183
184
185
186
187
188
189
190 public String getPath(final String characterEncoding) {
191 if (isReverseLookupRedirect()) {
192 final PathResolver pathResolver = this.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 private static class ForwardRouting implements Routing {
347
348
349 private final Class<?> actionClass;
350
351
352 private final Method actionMethod;
353
354
355
356
357 private ForwardRouting(final Class<?> actionClass,
358 final Method actionMethod) {
359 this.actionClass = actionClass;
360 this.actionMethod = actionMethod;
361 }
362
363
364
365
366 public Class<?> getActionClass() {
367 return actionClass;
368 }
369
370
371
372
373 public Method getActionMethod() {
374 return actionMethod;
375 }
376
377
378
379
380 public String getActionPath() {
381 return null;
382 }
383
384
385
386
387 public List<String> getUriParameterNames() {
388 return null;
389 }
390
391
392
393
394 public Pattern getPattern() {
395 return null;
396 }
397
398
399
400
401 public RequestMethod getRequestMethod() {
402 return null;
403 }
404
405
406
407
408 public String getOnSubmit() {
409 return null;
410 }
411
412
413
414
415 public int getPriority() {
416 return 0;
417 }
418
419
420
421
422 public boolean isAcceptable(final String requestMethod) {
423 return true;
424 }
425
426
427
428
429 @Override
430 public String toString() {
431 return new StringBuilder().append("[").append(actionMethod).append(
432 "]").toString();
433 }
434
435 }
436
437 }