1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.views.util;
23
24 import java.io.UnsupportedEncodingException;
25 import java.net.URLDecoder;
26 import java.net.URLEncoder;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Iterator;
30 import java.util.LinkedHashMap;
31 import java.util.List;
32 import java.util.Map;
33
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpServletResponse;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.apache.struts2.ServletActionContext;
40 import org.apache.struts2.StrutsConstants;
41
42 import com.opensymphony.xwork2.inject.Inject;
43 import com.opensymphony.xwork2.util.TextParseUtil;
44 import com.opensymphony.xwork2.util.ValueStack;
45
46
47 /***
48 * UrlHelper
49 *
50 */
51 public class UrlHelper {
52 private static final Log LOG = LogFactory.getLog(UrlHelper.class);
53
54 /***
55 * Default HTTP port (80).
56 */
57 private static final int DEFAULT_HTTP_PORT = 80;
58
59 /***
60 * Default HTTPS port (443).
61 */
62 private static final int DEFAULT_HTTPS_PORT = 443;
63
64 private static final String AMP = "&";
65
66 private static int httpPort = DEFAULT_HTTP_PORT;
67 private static int httpsPort = DEFAULT_HTTPS_PORT;
68 private static String customEncoding;
69
70
71 @Inject(StrutsConstants.STRUTS_URL_HTTP_PORT)
72 public static void setHttpPort(String val) {
73 httpPort = Integer.parseInt(val);
74 }
75
76 @Inject(StrutsConstants.STRUTS_URL_HTTPS_PORT)
77 public static void setHttpsPort(String val) {
78 httpsPort = Integer.parseInt(val);
79 }
80
81 @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
82 public static void setCustomEncoding(String val) {
83 customEncoding = val;
84 }
85
86 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params) {
87 return buildUrl(action, request, response, params, null, true, true);
88 }
89
90 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult) {
91 return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, false);
92 }
93
94 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort) {
95 return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, true);
96 }
97
98 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, boolean escapeAmp) {
99 StringBuffer link = new StringBuffer();
100
101 boolean changedScheme = false;
102
103
104
105 if (forceAddSchemeHostAndPort) {
106 String reqScheme = request.getScheme();
107 changedScheme = true;
108 link.append(scheme != null ? scheme : reqScheme);
109 link.append("://");
110 link.append(request.getServerName());
111
112 if (scheme != null) {
113
114 if (!scheme.equals(reqScheme)) {
115 if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT)) {
116 link.append(":");
117 link.append(scheme.equals("http") ? httpPort : httpsPort);
118 }
119
120 } else {
121 int reqPort = request.getServerPort();
122
123 if ((scheme.equals("http") && (reqPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && reqPort != DEFAULT_HTTPS_PORT)) {
124 link.append(":");
125 link.append(reqPort);
126 }
127 }
128 }
129 }
130 else if ((scheme != null) && !scheme.equals(request.getScheme())) {
131 changedScheme = true;
132 link.append(scheme);
133 link.append("://");
134 link.append(request.getServerName());
135
136 if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT)) {
137 link.append(":");
138 link.append(scheme.equals("http") ? httpPort : httpsPort);
139 }
140 }
141
142 if (action != null) {
143
144
145 if (action.startsWith("/") && includeContext) {
146 String contextPath = request.getContextPath();
147 if (!contextPath.equals("/")) {
148 link.append(contextPath);
149 }
150 } else if (changedScheme) {
151
152
153
154 String uri = (String) request.getAttribute("javax.servlet.forward.request_uri");
155
156
157 if (uri == null) {
158 uri = request.getRequestURI();
159 }
160
161 link.append(uri.substring(0, uri.lastIndexOf('/') + 1));
162 }
163
164
165 link.append(action);
166 } else {
167
168 String requestURI = (String) request.getAttribute("struts.request_uri");
169
170
171
172 if (requestURI == null) {
173 requestURI = (String) request.getAttribute("javax.servlet.forward.request_uri");
174 }
175
176
177 if (requestURI == null) {
178 requestURI = request.getRequestURI();
179 }
180
181 link.append(requestURI);
182 }
183
184
185 if (escapeAmp) {
186 buildParametersString(params, link);
187 } else {
188 buildParametersString(params, link, "&");
189 }
190
191 String result;
192
193 try {
194 result = encodeResult ? response.encodeURL(link.toString()) : link.toString();
195 } catch (Exception ex) {
196
197
198 result = link.toString();
199 }
200
201 return result;
202 }
203
204 public static void buildParametersString(Map params, StringBuffer link) {
205 buildParametersString(params, link, AMP);
206 }
207
208 public static void buildParametersString(Map params, StringBuffer link, String paramSeparator) {
209 if ((params != null) && (params.size() > 0)) {
210 if (link.toString().indexOf("?") == -1) {
211 link.append("?");
212 } else {
213 link.append(paramSeparator);
214 }
215
216
217 Iterator iter = params.entrySet().iterator();
218
219 String[] valueHolder = new String[1];
220
221 while (iter.hasNext()) {
222 Map.Entry entry = (Map.Entry) iter.next();
223 String name = (String) entry.getKey();
224 Object value = entry.getValue();
225
226 String[] values;
227
228 if (value instanceof String[]) {
229 values = (String[]) value;
230 } else {
231 valueHolder[0] = value.toString();
232 values = valueHolder;
233 }
234
235 for (int i = 0; i < values.length; i++) {
236 if (values[i] != null) {
237 link.append(name);
238 link.append('=');
239 link.append(translateAndEncode(values[i]));
240 }
241
242 if (i < (values.length - 1)) {
243 link.append(paramSeparator);
244 }
245 }
246
247 if (iter.hasNext()) {
248 link.append(paramSeparator);
249 }
250 }
251 }
252 }
253
254 /***
255 * Translates any script expressions using {@link com.opensymphony.xwork2.util.TextParseUtil#translateVariables} and
256 * encodes the URL using {@link java.net.URLEncoder#encode} with the encoding specified in the configuration.
257 *
258 * @param input
259 * @return the translated and encoded string
260 */
261 public static String translateAndEncode(String input) {
262 String translatedInput = translateVariable(input);
263 String encoding = getEncodingFromConfiguration();
264
265 try {
266 return URLEncoder.encode(translatedInput, encoding);
267 } catch (UnsupportedEncodingException e) {
268 LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
269 return translatedInput;
270 }
271 }
272
273 public static String translateAndDecode(String input) {
274 String translatedInput = translateVariable(input);
275 String encoding = getEncodingFromConfiguration();
276
277 try {
278 return URLDecoder.decode(translatedInput, encoding);
279 } catch (UnsupportedEncodingException e) {
280 LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
281 return translatedInput;
282 }
283 }
284
285 private static String translateVariable(String input) {
286 ValueStack valueStack = ServletActionContext.getContext().getValueStack();
287 String output = TextParseUtil.translateVariables(input, valueStack);
288 return output;
289 }
290
291 private static String getEncodingFromConfiguration() {
292 final String encoding;
293 if (customEncoding != null) {
294 encoding = customEncoding;
295 } else {
296 encoding = "UTF-8";
297 }
298 return encoding;
299 }
300
301 public static Map parseQueryString(String queryString) {
302 Map queryParams = new LinkedHashMap();
303 if (queryString != null) {
304 String[] params = queryString.split("&");
305 for (int a=0; a< params.length; a++) {
306 if (params[a].trim().length() > 0) {
307 String[] tmpParams = params[a].split("=");
308 String paramName = null;
309 String paramValue = "";
310 if (tmpParams.length > 0) {
311 paramName = tmpParams[0];
312 }
313 if (tmpParams.length > 1) {
314 paramValue = tmpParams[1];
315 }
316 if (paramName != null) {
317 String translatedParamValue = translateAndDecode(paramValue);
318
319 if(queryParams.containsKey(paramName)) {
320
321 Object currentParam = queryParams.get(paramName);
322 if(currentParam instanceof String) {
323 queryParams.put(paramName, new String[] {
324 (String) currentParam, translatedParamValue});
325 } else {
326 String currentParamValues[] = (String[]) currentParam;
327 List paramList = new ArrayList(Arrays
328 .asList(currentParamValues));
329 paramList.add(translatedParamValue);
330 String newParamValues[] = new String[paramList
331 .size()];
332 queryParams.put(paramName, paramList
333 .toArray(newParamValues));
334 }
335 } else {
336 queryParams.put(paramName, translatedParamValue);
337 }
338 }
339 }
340 }
341 }
342 return queryParams;
343 }
344 }