1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts.action;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.struts.config.ForwardConfig;
26 import org.apache.struts.util.ResponseUtils;
27
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34
35 /**
36 * <p> A subclass of {@link ActionForward} which is designed for use in
37 * redirecting requests, with support for adding parameters at runtime. <br/>
38 * An {@link ForwardConfig} (or subclass) can be passed to the constructor to
39 * copy its configuration: </p> <p>
40 * <pre>
41 * public ActionForward execute(ActionMapping mapping,
42 * ActionForm form,
43 * HttpServletRequest request,
44 * HttpServletResponse response)
45 * throws Exception {
46 * ActionRedirect redirect =
47 * new ActionRedirect(mapping.findForward("doRedirect"));
48 * redirect.addParameter("param1","value1");
49 * redirect.addParameter("param2","2");
50 * redirect.addParameter("param3","3.0");
51 * return redirect;
52 * }
53 * </pre>
54 * </p>
55 *
56 * @version $Rev: 513602 $ $Date: 2007-03-01 20:50:23 -0600 (Thu, 01 Mar 2007) $
57 */
58 public class ActionRedirect extends ActionForward {
59
60
61 /**
62 * <p>Default allocation size for string buffers.</p>
63 */
64 private static final int DEFAULT_BUFFER_SIZE = 256;
65
66
67
68 /**
69 * <p>Commons logging instance.</p>
70 */
71 protected static final Log LOG = LogFactory.getLog(ActionRedirect.class);
72
73
74
75 /**
76 * <p>Holds the redirect parameters. Each entry is either a String or a
77 * String[] depending on whether it has one or more entries.</p>
78 */
79 protected Map parameterValues = null;
80
81 /**
82 * <p>Holds the anchor value.</p>
83 */
84 protected String anchorValue = null;
85
86
87
88 /**
89 * <p>Construct a new instance with redirect set to true and initialize
90 * parameter lists.</p>
91 */
92 public ActionRedirect() {
93 setRedirect(true);
94 initializeParameters();
95 }
96
97 /**
98 * <p>Construct a new instance with the specified path and initialize
99 * parameter lists.</p>
100 *
101 * @param path Path for this instance
102 */
103 public ActionRedirect(String path) {
104 super(path);
105 setRedirect(true);
106 initializeParameters();
107 }
108
109 /**
110 * <p>Construct a new instance with the specified values and initialize
111 * parameter lists.</p>
112 *
113 * @param name Name of this instance
114 * @param path Path for this instance
115 * @param module Module prefix, if any
116 */
117 public ActionRedirect(String name, String path, String module) {
118 super(name, path, true);
119 setModule(module);
120 initializeParameters();
121 }
122
123 /**
124 * <p>Construct a new instance with a {@link ForwardConfig} object to copy
125 * name, path, contextRelative, and arbitrary property values from.</p>
126 *
127 * @param baseConfig the {@link ForwardConfig} to copy configuration
128 * values from
129 */
130 public ActionRedirect(ForwardConfig baseConfig) {
131 setName(baseConfig.getName());
132 setPath(baseConfig.getPath());
133 setModule(baseConfig.getModule());
134 setRedirect(true);
135 inheritProperties(baseConfig);
136 initializeParameters();
137 }
138
139
140
141 /**
142 * <p>Initializes the internal objects used to hold parameter values.</p>
143 */
144 private void initializeParameters() {
145 parameterValues = new HashMap();
146 }
147
148
149
150 /**
151 * <p>Adds the object's toString() to the list of parameters if it's not
152 * null, or an empty string with the given fieldName if it is.</p>
153 *
154 * @param fieldName the name to use for the parameter
155 * @param valueObj the value for this parameter
156 * @return The ActionRedirect instance this method is called on
157 */
158 public ActionRedirect addParameter(String fieldName, Object valueObj) {
159 String value = (valueObj != null) ? valueObj.toString() : "";
160
161 if (parameterValues == null) {
162 initializeParameters();
163 }
164
165
166 value = ResponseUtils.encodeURL(value);
167
168
169
170
171
172
173
174 Object currentValue = parameterValues.get(fieldName);
175
176 if (currentValue == null) {
177
178 parameterValues.put(fieldName, value);
179 } else if (currentValue instanceof String) {
180
181 String[] newValue = new String[2];
182
183 newValue[0] = (String) currentValue;
184 newValue[1] = value;
185 parameterValues.put(fieldName, newValue);
186 } else if (currentValue instanceof String[]) {
187
188 List newValues =
189 new ArrayList(Arrays.asList((Object[]) currentValue));
190
191 newValues.add(value);
192 parameterValues.put(fieldName,
193 newValues.toArray(new String[newValues.size()]));
194 }
195 return this;
196 }
197
198 /**
199 * <p>Adds an anchor to the path. Technically, the anchor value is
200 * just stored for later and will be added to the path in getPath().
201 * Note that this is a considerably simpler method than the
202 * addParmaeter method because aside from encoding the value, there
203 * isn't really anything to do. Passing in null is fine because that
204 * is the value that will be checked for later to determine whether
205 * to append an anchor to the path or not.</p>
206 *
207 * @param anchorValue The anchor to append to the path
208 * @return The ActionRefirect instance this method is called on
209 */
210 public ActionRedirect setAnchor(String anchorValue) {
211 this.anchorValue = ResponseUtils.encodeURL(anchorValue);
212 return this;
213 }
214
215 /**
216 * <p>Get the original path without the parameters added at runtime.</p>
217 *
218 * @return the original path as configured.
219 */
220 public String getOriginalPath() {
221 return super.getPath();
222 }
223
224 /**
225 * <p>Get the path for this object, including any parameters that may have
226 * been added at runtime.</p>
227 *
228 * @return The path for this object.
229 */
230 public String getPath() {
231
232 String originalPath = getOriginalPath();
233 String parameterString = getParameterString();
234 String anchorString = getAnchorString();
235
236 StringBuffer result = new StringBuffer(originalPath);
237
238 if ((parameterString != null) && (parameterString.length() > 0)) {
239
240 String paramSeparator = "?";
241
242
243 boolean needsParamSeparator = true;
244
245
246 int paramStartIndex = originalPath.indexOf("?");
247
248 if (paramStartIndex > 0) {
249
250 needsParamSeparator = (paramStartIndex != (originalPath.length()
251 - 1));
252
253 if (needsParamSeparator) {
254 paramSeparator = "&";
255 }
256 }
257
258 if (needsParamSeparator) {
259 result.append(paramSeparator);
260 }
261
262 result.append(parameterString);
263 }
264
265
266 result.append(anchorString);
267
268
269 return result.toString();
270 }
271
272 /**
273 * <p>Forms the string containing the parameters
274 * passed onto this object thru calls to addParameter().</p>
275 *
276 * @return a string which can be appended to the URLs. The
277 * return string includes a leading hash
278 * mark (#).
279 */
280 public String getAnchorString() {
281 String retVal = "";
282 if (anchorValue != null) {
283 retVal = "#" + anchorValue;
284 }
285 return retVal;
286 }
287
288 /**
289 * <p>Forms the string containing the parameters passed onto this object
290 * thru calls to addParameter().</p>
291 *
292 * @return a string which can be appended to the URLs. The return string
293 * does not include a leading question mark (?).
294 */
295 public String getParameterString() {
296 StringBuffer strParam = new StringBuffer(DEFAULT_BUFFER_SIZE);
297
298
299 Iterator iterator = parameterValues.keySet().iterator();
300
301 while (iterator.hasNext()) {
302
303 String paramName = (String) iterator.next();
304
305
306 Object value = parameterValues.get(paramName);
307
308 if (value instanceof String) {
309
310 strParam.append(paramName).append("=").append(value);
311 } else if (value instanceof String[]) {
312
313 String[] values = (String[]) value;
314
315 for (int i = 0; i < values.length; i++) {
316 strParam.append(paramName).append("=").append(values[i]);
317
318 if (i < (values.length - 1)) {
319 strParam.append("&");
320 }
321 }
322 }
323
324 if (iterator.hasNext()) {
325 strParam.append("&");
326 }
327 }
328
329 return strParam.toString();
330 }
331
332
333
334 /**
335 * <p>Return a string description of this object.</p>
336 *
337 * @return a string containing the original path for this object and the
338 * parameters it currently holds
339 */
340 public String toString() {
341 StringBuffer result = new StringBuffer(DEFAULT_BUFFER_SIZE);
342
343 result.append("ActionRedirect [");
344 result.append("originalPath=").append(getOriginalPath()).append(";");
345 result.append("parameterString=").append(getParameterString()).append("]");
346 result.append("anchorString=").append(getAnchorString()).append("]");
347
348 return result.toString();
349 }
350 }