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