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