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