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