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