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