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.Collections;
28 import java.util.Iterator;
29 import java.util.LinkedHashMap;
30 import java.util.Map;
31
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpServletResponse;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.struts2.ServletActionContext;
38 import org.apache.struts2.StrutsConstants;
39
40 import com.opensymphony.xwork2.ActionContext;
41 import com.opensymphony.xwork2.inject.Inject;
42 import com.opensymphony.xwork2.util.TextParseUtil;
43 import com.opensymphony.xwork2.util.ValueStack;
44
45
46 /***
47 * UrlHelper
48 *
49 */
50 public class UrlHelper {
51 private static final Log LOG = LogFactory.getLog(UrlHelper.class);
52
53 /***
54 * Default HTTP port (80).
55 */
56 private static final int DEFAULT_HTTP_PORT = 80;
57
58 /***
59 * Default HTTPS port (443).
60 */
61 private static final int DEFAULT_HTTPS_PORT = 443;
62
63 private static final String AMP = "&";
64
65 private static int httpPort = DEFAULT_HTTP_PORT;
66 private static int httpsPort = DEFAULT_HTTPS_PORT;
67 private static String customEncoding;
68
69 @Inject(StrutsConstants.STRUTS_URL_HTTP_PORT)
70 public static void setHttpPort(String val) {
71 httpPort = Integer.parseInt(val);
72 }
73
74 @Inject(StrutsConstants.STRUTS_URL_HTTPS_PORT)
75 public static void setHttpsPort(String val) {
76 httpsPort = Integer.parseInt(val);
77 }
78
79 @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
80 public static void setCustomEncoding(String val) {
81 customEncoding = val;
82 }
83
84 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params) {
85 return buildUrl(action, request, response, params, null, true, true);
86 }
87
88 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult) {
89 return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, false);
90 }
91
92 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort) {
93 StringBuffer link = new StringBuffer();
94
95 boolean changedScheme = false;
96
97
98
99 if (forceAddSchemeHostAndPort) {
100 String reqScheme = request.getScheme();
101 changedScheme = true;
102 link.append(scheme != null ? scheme : reqScheme);
103 link.append("://");
104 link.append(request.getServerName());
105
106 if (scheme != null) {
107 if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT))
108 {
109 link.append(":");
110 link.append(scheme.equals("http") ? httpPort : httpsPort);
111 }
112 }
113 }
114 else if (
115 (scheme != null) && !scheme.equals(request.getScheme())) {
116 changedScheme = true;
117 link.append(scheme);
118 link.append("://");
119 link.append(request.getServerName());
120
121 if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT))
122 {
123 link.append(":");
124 link.append(scheme.equals("http") ? httpPort : httpsPort);
125 }
126 }
127
128 if (action != null) {
129
130
131 if (action.startsWith("/") && includeContext) {
132 String contextPath = request.getContextPath();
133 if (!contextPath.equals("/")) {
134 link.append(contextPath);
135 }
136 } else if (changedScheme) {
137
138
139
140 String uri = (String) request.getAttribute("javax.servlet.forward.request_uri");
141
142
143 if (uri == null) {
144 uri = request.getRequestURI();
145 }
146
147 link.append(uri.substring(0, uri.lastIndexOf('/') + 1));
148 }
149
150
151 link.append(action);
152 } else {
153
154 String requestURI = (String) request.getAttribute("struts.request_uri");
155
156
157
158 if (requestURI == null) {
159 requestURI = (String) request.getAttribute("javax.servlet.forward.request_uri");
160 }
161
162
163 if (requestURI == null) {
164 requestURI = request.getRequestURI();
165 }
166
167 link.append(requestURI);
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 (customEncoding != null) {
276 encoding = customEncoding;
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 }