1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package org.objectledge.parameters;
30
31 import java.io.UnsupportedEncodingException;
32 import java.net.URLDecoder;
33 import java.util.Enumeration;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.LinkedHashMap;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.StringTokenizer;
40
41 import javax.servlet.http.HttpServletRequest;
42
43 import org.objectledge.context.Context;
44 import org.objectledge.web.mvc.tools.LinkTool;
45
46 /***
47 * Request parameters contain parameters from the request sorted by their names.
48 *
49 * <p>TODO: figure out a way to discover URL parameters encoding, now UTF-8 is used, but
50 * browsers encode GET form parameters using form page encoding thus rendering UTF-8 decoding
51 * useless. Problems:</p>
52 * <ul>
53 * <li>browsers encode URLs using UTF-8 by default (URLs typed in th location bar)</li>
54 * <li>browsers do not send any information on parameters encoding</li>
55 * </ul>
56 *
57 * @author <a href="mailto:dgajda@caltha.pl">Damian Gajda</a>
58 * @author <a href="mailto:pablo@caltha.pl">Pawel Potempski</a>
59 * @version $Id: RequestParameters.java,v 1.17 2005/08/05 12:48:27 rafal Exp $
60 */
61 public class RequestParameters extends SortedParameters
62 {
63 private Set<String> pathParams = new HashSet<String>();
64 private Set<String> queryParams = new HashSet<String>();
65 private Set<String> postParams = new HashSet<String>();
66
67 /***
68 * Usefull method to retrieve parameters from context.
69 *
70 * @param context the context.
71 * @return the request parameters.
72 */
73 public static RequestParameters getRequestParameters(Context context)
74 {
75 return (RequestParameters)context.getAttribute(RequestParameters.class);
76 }
77
78 /***
79 * No arg constructor for mocking.
80 */
81 protected RequestParameters()
82 {
83
84 }
85
86 /***
87 * Create the parameter container with parameters found in http request.
88 *
89 * @param request the request
90 * @throws IllegalArgumentException if illegal escape sequences appears.
91 */
92 public RequestParameters(HttpServletRequest request)
93 throws IllegalArgumentException
94 {
95 super();
96
97
98 addURLParams(request.getQueryString(), "&=");
99
100
101
102 HashMap queryStringParams = new HashMap();
103 queryStringParams.putAll(this.map);
104 queryParams.addAll(queryStringParams.keySet());
105
106
107 Enumeration names = request.getParameterNames();
108 while (names.hasMoreElements())
109 {
110 String name = (String)names.nextElement();
111 String[] values = request.getParameterValues(name);
112
113 int start = 0;
114 if(queryStringParams.containsKey(name))
115 {
116 start = ((String[])(queryStringParams.get(name))).length;
117 }
118 for (int i = start; i < values.length; i++)
119 {
120 add(name, values[i]);
121 }
122 }
123 postParams.addAll(map.keySet());
124 for(String name : map.keySet())
125 {
126 if(queryStringParams.containsKey(name)
127 && ((String[])queryStringParams.get(name)).length == getStrings(name).length)
128 {
129 postParams.remove(name);
130 }
131 }
132
133
134 addURLParams(request.getPathInfo(), "/");
135 pathParams.addAll(map.keySet());
136 pathParams.removeAll(queryParams);
137 pathParams.removeAll(postParams);
138
139
140 Map tmp = new LinkedHashMap(map);
141 map = tmp;
142 }
143
144 private static final int START = 0;
145 private static final int NAME = 1;
146 private static final int SEPARATOR_AFTER_NAME = 2;
147 private static final int VALUE = 3;
148 private static final int SEPARATOR_AFTER_VALUE = 4;
149
150 private void addURLParams(String urlPart, String separator)
151 {
152 if (urlPart == null)
153 {
154 return;
155 }
156
157 try
158 {
159 StringTokenizer st = new StringTokenizer(urlPart, separator, true);
160 int state = START;
161 String name = null;
162 while (st.hasMoreTokens())
163 {
164 String token = st.nextToken();
165
166 if(token.length() == 1 && separator.indexOf(token.charAt(0)) > -1 )
167 {
168 switch(state)
169 {
170 case START:
171 state = NAME;
172 break;
173 case SEPARATOR_AFTER_NAME:
174 state = VALUE;
175 break;
176 case SEPARATOR_AFTER_VALUE:
177 state = NAME;
178 break;
179 case VALUE:
180 add(name, "");
181 name = null;
182 state = NAME;
183 break;
184 case NAME:
185 throw new IllegalStateException("empty parameter name");
186 default:
187 throw new IllegalStateException(
188 "illegal state while parsing params");
189 }
190 }
191
192 else
193 {
194 switch(state)
195 {
196 case START:
197 case NAME:
198 name = URLDecoder.decode(token, LinkTool.PARAMETER_ENCODING);
199 state = SEPARATOR_AFTER_NAME;
200 break;
201 case VALUE:
202 add(name, URLDecoder.decode(token, LinkTool.PARAMETER_ENCODING));
203 name = null;
204 state = SEPARATOR_AFTER_VALUE;
205 break;
206 default:
207 break;
208 }
209 }
210 }
211 }
212
213 catch (UnsupportedEncodingException e)
214 {
215 throw new IllegalArgumentException("Unsupported encoding exception " + e.getMessage());
216 }
217
218 }
219
220 /***
221 * Checks if the parameter was passed in through request path info.
222 *
223 * @param name name of the parameter.
224 * @return <code>true</code> if the parameter was passed in through path info.
225 */
226 public boolean isPathInfoParameter(String name)
227 {
228 return pathParams.contains(name);
229 }
230
231 /***
232 * Checks if the parameter was passed in through request query string.
233 *
234 * @param name name of the parameter.
235 * @return <code>true</code> if the parameter was passed in through request query string.
236 */
237 public boolean isQueryStringParameter(String name)
238 {
239 return queryParams.contains(name);
240 }
241
242 /***
243 * Checks if the parameter was passed in through POST request body.
244 *
245 * @param name name of the parameter.
246 * @return <code>true</code> if the parameter was passed through POST request body.
247 */
248 public boolean isPOSTParameter(String name)
249 {
250 return postParams.contains(name);
251 }
252
253 /***
254 * To be used by FileUploadValve, that handles multipart/form-data POSTs.
255 *
256 * @param name of the parameter.
257 * @param value value of the parameter.
258 */
259 public void addPOSTParameter(String name, String value)
260 {
261 super.add(name, value);
262 postParams.add(name);
263 }
264 }