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.internal.util.LogMessages.format;
19
20 import java.net.MalformedURLException;
21 import java.net.URL;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import javax.servlet.http.HttpServletRequest;
27 import javax.servlet.http.HttpServletResponse;
28
29 import org.seasar.cubby.internal.util.MetaUtils;
30 import org.seasar.cubby.internal.util.QueryStringBuilder;
31 import org.seasar.cubby.internal.util.StringUtils;
32 import org.seasar.cubby.routing.PathResolver;
33 import org.seasar.cubby.spi.PathResolverProvider;
34 import org.seasar.cubby.spi.ProviderFactory;
35 import org.seasar.cubby.util.LinkBuilder;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39
40
41
42
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
99
100 public class Redirect implements ActionResult {
101
102
103 private static final Logger logger = LoggerFactory
104 .getLogger(Redirect.class);
105
106
107 private static final Map<String, String[]> EMPTY_PARAMETERS = Collections
108 .emptyMap();
109
110
111 private final LinkBuilder linkBuilder = new LinkBuilder();
112
113
114 private String path;
115
116
117 private Class<?> actionClass;
118
119
120 private String methodName;
121
122
123 private Map<String, String[]> parameters;
124
125
126 private String characterEncoding;
127
128
129 private boolean encodeURL = true;
130
131
132
133
134
135
136
137 public Redirect(final String path) {
138 this.path = path;
139 }
140
141
142
143
144
145
146
147
148
149
150 public Redirect(final String path, final String protocol) {
151 this(path);
152 linkBuilder.setProtocol(protocol);
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166 public Redirect(final String path, final String protocol, final int port) {
167 this(path);
168 linkBuilder.setProtocol(protocol);
169 linkBuilder.setPort(port);
170 }
171
172
173
174
175
176
177
178
179 public Redirect(final Class<?> actionClass) {
180 this(actionClass, "index");
181 }
182
183
184
185
186
187
188
189
190
191
192 public Redirect(final Class<?> actionClass, final String methodName) {
193 this(actionClass, methodName, EMPTY_PARAMETERS);
194 }
195
196
197
198
199
200
201
202
203
204
205
206
207 public Redirect(final Class<?> actionClass, final String methodName,
208 final Map<String, String[]> parameters) {
209 this.actionClass = actionClass;
210 this.methodName = methodName;
211 this.parameters = parameters;
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227 public Redirect(final Class<?> actionClass, final String methodName,
228 final Map<String, String[]> parameters, final String protocol) {
229 this(actionClass, methodName, parameters);
230 linkBuilder.setProtocol(protocol);
231 }
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 public Redirect(final Class<?> actionClass, final String methodName,
249 final Map<String, String[]> parameters, final String protocol,
250 final int port) {
251 this(actionClass, methodName, parameters);
252 linkBuilder.setProtocol(protocol);
253 linkBuilder.setPort(port);
254 }
255
256
257
258
259
260
261
262
263 public String getPath(final String characterEncoding) {
264 if (isReverseLookupRedirect()) {
265 final PathResolverProvider pathResolverProvider = ProviderFactory
266 .get(PathResolverProvider.class);
267 final PathResolver pathResolver = pathResolverProvider
268 .getPathResolver();
269 final String redirectPath = pathResolver.reverseLookup(actionClass,
270 methodName, parameters, characterEncoding);
271 this.path = redirectPath;
272 }
273 return this.path;
274 }
275
276
277
278
279
280
281 private boolean isReverseLookupRedirect() {
282 return this.actionClass != null && this.methodName != null
283 && this.parameters != null;
284 }
285
286
287
288
289 public void execute(final ActionContext actionContext,
290 final HttpServletRequest request, final HttpServletResponse response)
291 throws Exception {
292 final String characterEncoding;
293 if (this.characterEncoding == null) {
294 characterEncoding = request.getCharacterEncoding();
295 } else {
296 characterEncoding = this.characterEncoding;
297 }
298 final String redirectURL = calculateRedirectURL(
299 getPath(characterEncoding), actionContext.getActionClass(),
300 request);
301 final String encodedRedirectURL = encodeURL(redirectURL, response);
302 if (logger.isDebugEnabled()) {
303 logger.debug(format("DCUB0003", encodedRedirectURL));
304 }
305 response.sendRedirect(encodedRedirectURL);
306 }
307
308
309
310
311
312
313
314
315
316
317
318
319 protected String calculateRedirectURL(final String path,
320 final Class<?> actionClass, final HttpServletRequest request) {
321 try {
322 final String redirectURL = new URL(path).toExternalForm();
323 return redirectURL;
324 } catch (final MalformedURLException e) {
325 final String redirectURL = calculateInternalRedirectURL(path,
326 actionClass, request);
327 return redirectURL;
328 }
329 }
330
331
332
333
334
335
336
337
338
339
340
341
342 private String calculateInternalRedirectURL(final String path,
343 final Class<?> actionClass, final HttpServletRequest request) {
344 final String redirectPath;
345 final String contextPath;
346 if ("/".equals(request.getContextPath())) {
347 contextPath = "";
348 } else {
349 contextPath = request.getContextPath();
350 }
351 if (path.startsWith("/")) {
352 redirectPath = contextPath + path;
353 } else {
354 final String actionDirectory = MetaUtils
355 .getActionDirectory(actionClass);
356 if (StringUtils.isEmpty(actionDirectory)) {
357 final StringBuilder builder = new StringBuilder();
358 builder.append(contextPath);
359 if (!contextPath.endsWith("/")) {
360 builder.append("/");
361 }
362 builder.append(path);
363 redirectPath = builder.toString();
364 } else {
365 final StringBuilder builder = new StringBuilder();
366 builder.append(contextPath);
367 if (!contextPath.endsWith("/")
368 && !actionDirectory.startsWith("/")) {
369 builder.append("/");
370 }
371 builder.append(actionDirectory);
372 if (!actionDirectory.endsWith("/")) {
373 builder.append("/");
374 }
375 builder.append(path);
376 redirectPath = builder.toString();
377 }
378 }
379
380 try {
381 return linkBuilder.file(redirectPath).toLink(request);
382 } catch (final MalformedURLException e) {
383 throw new ActionException(e);
384 }
385 }
386
387
388
389
390
391
392
393
394
395
396
397 protected String encodeURL(final String url,
398 final HttpServletResponse response) {
399 if (encodeURL) {
400 return response.encodeRedirectURL(url);
401 } else {
402 return url;
403 }
404 }
405
406
407
408
409
410
411
412
413
414
415
416 public Redirect noEncodeURL() {
417 this.encodeURL = false;
418 return this;
419 }
420
421
422
423
424
425
426
427
428
429
430
431 public Redirect param(final String paramName, final Object paramValue) {
432 return param(paramName, new String[] { paramValue.toString() });
433 }
434
435
436
437
438
439
440
441
442
443
444
445 public Redirect param(final String paramName, final Object[] paramValues) {
446 return param(paramName, toStringArray(paramValues));
447 }
448
449
450
451
452
453
454
455
456
457
458
459 public Redirect param(final String paramName, final String[] paramValues) {
460 if (isReverseLookupRedirect()) {
461 if (this.parameters == EMPTY_PARAMETERS) {
462 this.parameters = new HashMap<String, String[]>();
463 }
464 this.parameters.put(paramName, paramValues);
465 } else {
466 final QueryStringBuilder builder = new QueryStringBuilder(this.path);
467 builder.addParam(paramName, paramValues);
468 this.path = builder.toString();
469 }
470 return this;
471 }
472
473
474
475
476
477
478
479
480
481
482
483 private String[] toStringArray(final Object[] paramValues) {
484 final String[] values = new String[paramValues.length];
485 for (int i = 0; i < paramValues.length; i++) {
486 values[i] = paramValues[i].toString();
487 }
488 return values;
489 }
490
491
492
493
494
495
496
497
498
499 public Redirect characterEncoding(final String characterEncoding) {
500 this.characterEncoding = characterEncoding;
501 return this;
502 }
503
504
505
506
507
508
509
510 @Deprecated
511 public String getPath() {
512 return getPath("UTF-8");
513 }
514
515 }