%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.turbine.util.parser.DefaultParameterParser |
|
|
1 | package org.apache.turbine.util.parser; |
|
2 | ||
3 | /* |
|
4 | * Copyright 2001-2005 The Apache Software Foundation. |
|
5 | * |
|
6 | * Licensed under the Apache License, Version 2.0 (the "License") |
|
7 | * you may not use this file except in compliance with the License. |
|
8 | * You may obtain a copy of the License at |
|
9 | * |
|
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
11 | * |
|
12 | * Unless required by applicable law or agreed to in writing, software |
|
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
15 | * See the License for the specific language governing permissions and |
|
16 | * limitations under the License. |
|
17 | */ |
|
18 | ||
19 | import java.net.URLDecoder; |
|
20 | ||
21 | import java.util.Enumeration; |
|
22 | import java.util.HashMap; |
|
23 | import java.util.Iterator; |
|
24 | import java.util.Map; |
|
25 | import java.util.Set; |
|
26 | import java.util.StringTokenizer; |
|
27 | ||
28 | import javax.servlet.http.HttpServletRequest; |
|
29 | ||
30 | import org.apache.commons.collections.set.CompositeSet; |
|
31 | import org.apache.commons.fileupload.FileItem; |
|
32 | import org.apache.commons.lang.ArrayUtils; |
|
33 | import org.apache.commons.logging.Log; |
|
34 | import org.apache.commons.logging.LogFactory; |
|
35 | ||
36 | import org.apache.turbine.TurbineConstants; |
|
37 | import org.apache.turbine.services.upload.TurbineUpload; |
|
38 | import org.apache.turbine.services.upload.UploadService; |
|
39 | import org.apache.turbine.util.TurbineException; |
|
40 | import org.apache.turbine.util.pool.Recyclable; |
|
41 | ||
42 | /** |
|
43 | * DefaultParameterParser is a utility object to handle parsing and |
|
44 | * retrieving the data passed via the GET/POST/PATH_INFO arguments. |
|
45 | * |
|
46 | * <p>NOTE: The name= portion of a name=value pair may be converted |
|
47 | * to lowercase or uppercase when the object is initialized and when |
|
48 | * new data is added. This behaviour is determined by the url.case.folding |
|
49 | * property in TurbineResources.properties. Adding a name/value pair may |
|
50 | * overwrite existing name=value pairs if the names match: |
|
51 | * |
|
52 | * <pre> |
|
53 | * ParameterParser pp = data.getParameters(); |
|
54 | * pp.add("ERROR",1); |
|
55 | * pp.add("eRrOr",2); |
|
56 | * int result = pp.getInt("ERROR"); |
|
57 | * </pre> |
|
58 | * |
|
59 | * In the above example, result is 2. |
|
60 | * |
|
61 | * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a> |
|
62 | * @author <a href="mailto:jon@clearink.com">Jon S. Stevens</a> |
|
63 | * @author <a href="mailto:sean@informage.net">Sean Legassick</a> |
|
64 | * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> |
|
65 | * @version $Id: DefaultParameterParser.java 280146 2005-09-11 15:40:20Z henning $ |
|
66 | */ |
|
67 | 21 | public class DefaultParameterParser |
68 | extends BaseValueParser |
|
69 | implements ParameterParser, Recyclable |
|
70 | { |
|
71 | /** Logging */ |
|
72 | 84 | private static Log log = LogFactory.getLog(DefaultParameterParser.class); |
73 | ||
74 | /** The servlet request to parse. */ |
|
75 | 4 | private HttpServletRequest request = null; |
76 | ||
77 | /** The raw data of a file upload. */ |
|
78 | 4 | private byte[] uploadData = null; |
79 | ||
80 | /** Map of request parameters to FileItem[]'s */ |
|
81 | 4 | private Map fileParameters = new HashMap(); |
82 | ||
83 | /** Turbine Upload Service reference */ |
|
84 | 42 | private static UploadService uploadService = null; |
85 | ||
86 | /** Do we have an upload Service? */ |
|
87 | 42 | private static boolean uploadServiceIsAvailable = false; |
88 | ||
89 | /** |
|
90 | * Create a new empty instance of ParameterParser. Uses the |
|
91 | * default character encoding (US-ASCII). |
|
92 | * |
|
93 | * <p>To add name/value pairs to this set of parameters, use the |
|
94 | * <code>add()</code> methods. |
|
95 | */ |
|
96 | public DefaultParameterParser() |
|
97 | { |
|
98 | 4 | super(); |
99 | 4 | configureUploadService(); |
100 | 4 | } |
101 | ||
102 | /** |
|
103 | * Create a new empty instance of ParameterParser. Takes a |
|
104 | * character encoding name to use when converting strings to |
|
105 | * bytes. |
|
106 | * |
|
107 | * <p>To add name/value pairs to this set of parameters, use the |
|
108 | * <code>add()</code> methods. |
|
109 | * |
|
110 | * @param characterEncoding The character encoding of strings. |
|
111 | */ |
|
112 | public DefaultParameterParser(String characterEncoding) |
|
113 | { |
|
114 | 0 | super(characterEncoding); |
115 | 0 | configureUploadService(); |
116 | 0 | } |
117 | ||
118 | /** |
|
119 | * Checks for availability of the Upload Service. We do this |
|
120 | * check only once at Startup, because the getService() call |
|
121 | * is really expensive and we don't have to run it every time |
|
122 | * we process a request. |
|
123 | */ |
|
124 | private void configureUploadService() |
|
125 | { |
|
126 | 4 | uploadServiceIsAvailable = TurbineUpload.isAvailable(); |
127 | 4 | if (uploadServiceIsAvailable) |
128 | { |
|
129 | 4 | uploadService = TurbineUpload.getService(); |
130 | } |
|
131 | 4 | } |
132 | ||
133 | /** |
|
134 | * Disposes the parser. |
|
135 | */ |
|
136 | public void dispose() |
|
137 | { |
|
138 | 0 | this.request = null; |
139 | 0 | this.uploadData = null; |
140 | 0 | this.fileParameters.clear(); |
141 | 0 | super.dispose(); |
142 | 0 | } |
143 | ||
144 | /** |
|
145 | * Gets the parsed servlet request. |
|
146 | * |
|
147 | * @return the parsed servlet request or null. |
|
148 | */ |
|
149 | public HttpServletRequest getRequest() |
|
150 | { |
|
151 | 0 | return request; |
152 | } |
|
153 | ||
154 | /** |
|
155 | * Sets the servlet request to the parser. This requires a |
|
156 | * valid HttpServletRequest object. It will attempt to parse out |
|
157 | * the GET/POST/PATH_INFO data and store the data into a Map. |
|
158 | * There are convenience methods for retrieving the data as a |
|
159 | * number of different datatypes. The PATH_INFO data must be a |
|
160 | * URLEncoded() string. |
|
161 | * <p> |
|
162 | * To add name/value pairs to this set of parameters, use the |
|
163 | * <code>add()</code> methods. |
|
164 | * |
|
165 | * @param request An HttpServletRequest. |
|
166 | */ |
|
167 | public void setRequest(HttpServletRequest request) |
|
168 | { |
|
169 | 0 | clear(); |
170 | ||
171 | 0 | uploadData = null; |
172 | ||
173 | 0 | String enc = request.getCharacterEncoding(); |
174 | 0 | setCharacterEncoding(enc != null |
175 | ? enc |
|
176 | : TurbineConstants.PARAMETER_ENCODING_DEFAULT); |
|
177 | ||
178 | 0 | String contentType = request.getHeader("Content-type"); |
179 | ||
180 | 0 | if (uploadServiceIsAvailable |
181 | && uploadService.getAutomatic() |
|
182 | && contentType != null |
|
183 | && contentType.startsWith("multipart/form-data")) |
|
184 | { |
|
185 | 0 | if (log.isDebugEnabled()) |
186 | { |
|
187 | 0 | log.debug("Running the Turbine Upload Service"); |
188 | } |
|
189 | ||
190 | try |
|
191 | { |
|
192 | 0 | TurbineUpload.parseRequest(request, this); |
193 | } |
|
194 | 0 | catch (TurbineException e) |
195 | { |
|
196 | 0 | log.error("File upload failed", e); |
197 | 0 | } |
198 | } |
|
199 | ||
200 | 0 | for (Enumeration names = request.getParameterNames(); |
201 | 0 | names.hasMoreElements();) |
202 | { |
|
203 | 0 | String paramName = (String) names.nextElement(); |
204 | 0 | add(paramName, |
205 | request.getParameterValues(paramName)); |
|
206 | } |
|
207 | ||
208 | // Also cache any pathinfo variables that are passed around as |
|
209 | // if they are query string data. |
|
210 | try |
|
211 | { |
|
212 | 0 | boolean isNameTok = true; |
213 | 0 | String paramName = null; |
214 | 0 | String paramValue = null; |
215 | ||
216 | 0 | for ( StringTokenizer st = |
217 | new StringTokenizer(request.getPathInfo(), "/"); |
|
218 | 0 | st.hasMoreTokens();) |
219 | { |
|
220 | 0 | if (isNameTok) |
221 | { |
|
222 | 0 | paramName = URLDecoder.decode(st.nextToken()); |
223 | 0 | isNameTok = false; |
224 | } |
|
225 | else |
|
226 | { |
|
227 | 0 | paramValue = URLDecoder.decode(st.nextToken()); |
228 | 0 | if (paramName.length() > 0) |
229 | { |
|
230 | 0 | add(paramName, paramValue); |
231 | } |
|
232 | 0 | isNameTok = true; |
233 | } |
|
234 | } |
|
235 | } |
|
236 | 0 | catch (Exception e) |
237 | { |
|
238 | // If anything goes wrong above, don't worry about it. |
|
239 | // Chances are that the path info was wrong anyways and |
|
240 | // things that depend on it being right will fail later |
|
241 | // and should be caught later. |
|
242 | 0 | } |
243 | ||
244 | 0 | this.request = request; |
245 | ||
246 | 0 | if (log.isDebugEnabled()) |
247 | { |
|
248 | 0 | log.debug("Parameters found in the Request:"); |
249 | 0 | for (Iterator it = keySet().iterator(); it.hasNext();) |
250 | { |
|
251 | 0 | String key = (String) it.next(); |
252 | 0 | log.debug("Key: " + key + " -> " + getString(key)); |
253 | } |
|
254 | } |
|
255 | 0 | } |
256 | ||
257 | /** |
|
258 | * Sets the uploadData byte[] |
|
259 | * |
|
260 | * @param uploadData A byte[] with data. |
|
261 | */ |
|
262 | public void setUploadData(byte[] uploadData) |
|
263 | { |
|
264 | 0 | this.uploadData = uploadData; |
265 | 0 | } |
266 | ||
267 | /** |
|
268 | * Gets the uploadData byte[] |
|
269 | * |
|
270 | * @return uploadData A byte[] with data. |
|
271 | */ |
|
272 | public byte[] getUploadData() |
|
273 | { |
|
274 | 0 | return uploadData; |
275 | } |
|
276 | ||
277 | /** |
|
278 | * Add a FileItem object as a parameters. If there are any |
|
279 | * FileItems already associated with the name, append to the |
|
280 | * array. The reason for this is that RFC 1867 allows multiple |
|
281 | * files to be associated with single HTML input element. |
|
282 | * |
|
283 | * @param name A String with the name. |
|
284 | * @param value A FileItem with the value. |
|
285 | * @deprecated Use add(String name, FileItem item) |
|
286 | */ |
|
287 | public void append(String name, FileItem item) |
|
288 | { |
|
289 | 0 | add(name, item); |
290 | 0 | } |
291 | ||
292 | /** |
|
293 | * Add a FileItem object as a parameters. If there are any |
|
294 | * FileItems already associated with the name, append to the |
|
295 | * array. The reason for this is that RFC 1867 allows multiple |
|
296 | * files to be associated with single HTML input element. |
|
297 | * |
|
298 | * @param name A String with the name. |
|
299 | * @param value A FileItem with the value. |
|
300 | */ |
|
301 | public void add(String name, FileItem item) |
|
302 | { |
|
303 | 4 | FileItem[] items = getFileItemParam(name); |
304 | 4 | items = (FileItem []) ArrayUtils.add(items, item); |
305 | 4 | putFileItemParam(name, items); |
306 | 4 | } |
307 | ||
308 | /** |
|
309 | * Gets the set of keys (FileItems and regular parameters) |
|
310 | * |
|
311 | * @return A <code>Set</code> of the keys. |
|
312 | */ |
|
313 | public Set keySet() |
|
314 | { |
|
315 | 10 | return new CompositeSet(class="keyword">new Set[] { super.keySet(), fileParameters.keySet() } ); |
316 | } |
|
317 | ||
318 | /** |
|
319 | * Determine whether a given key has been inserted. All keys are |
|
320 | * stored in lowercase strings, so override method to account for |
|
321 | * this. |
|
322 | * |
|
323 | * @param key An Object with the key to search for. |
|
324 | * @return True if the object is found. |
|
325 | */ |
|
326 | public boolean containsKey(Object key) |
|
327 | { |
|
328 | 6 | if (super.containsKey(key)) |
329 | { |
|
330 | 2 | return true; |
331 | } |
|
332 | ||
333 | 4 | return fileParameters.containsKey(convert(String.valueOf(key))); |
334 | } |
|
335 | ||
336 | ||
337 | /** |
|
338 | * Return a FileItem object for the given name. If the name does |
|
339 | * not exist or the object stored is not a FileItem, return null. |
|
340 | * |
|
341 | * @param name A String with the name. |
|
342 | * @return A FileItem. |
|
343 | */ |
|
344 | public FileItem getFileItem(String name) |
|
345 | { |
|
346 | 0 | FileItem [] value = getFileItemParam(name); |
347 | ||
348 | 0 | return (value == null |
349 | || value.length == 0) |
|
350 | ? null : value[0]; |
|
351 | } |
|
352 | ||
353 | /** |
|
354 | * Return an array of FileItem objects for the given name. If the |
|
355 | * name does not exist, return null. |
|
356 | * |
|
357 | * @param name A String with the name. |
|
358 | * @return An Array of FileItems or null. |
|
359 | */ |
|
360 | public FileItem[] getFileItems(String name) |
|
361 | { |
|
362 | 0 | return getFileItemParam(name); |
363 | } |
|
364 | ||
365 | /** |
|
366 | * Puts a key into the parameters map. Makes sure that the name is always |
|
367 | * mapped correctly. This method also enforces the usage of arrays for the |
|
368 | * parameters. |
|
369 | * |
|
370 | * @param name A String with the name. |
|
371 | * @param value An array of Objects with the values. |
|
372 | * |
|
373 | */ |
|
374 | protected void putFileItemParam(final String name, class="keyword">final FileItem [] value) |
|
375 | { |
|
376 | 4 | String key = convert(name); |
377 | 4 | if (key != null) |
378 | { |
|
379 | 4 | fileParameters.put(key, value); |
380 | } |
|
381 | 4 | } |
382 | ||
383 | /** |
|
384 | * fetches a key from the parameters map. Makes sure that the name is |
|
385 | * always mapped correctly. |
|
386 | * |
|
387 | * @param name A string with the name |
|
388 | * |
|
389 | * @return the value object array or null if not set |
|
390 | */ |
|
391 | protected FileItem [] getFileItemParam(final String name) |
|
392 | { |
|
393 | 6 | String key = convert(name); |
394 | ||
395 | 6 | return (key != null) ? (FileItem []) fileParameters.get(key) : class="keyword">null; |
396 | } |
|
397 | ||
398 | /** |
|
399 | * This method is only used in toString() and can be used by |
|
400 | * derived classes to add their local parameters to the toString() |
|
401 | ||
402 | * @param name A string with the name |
|
403 | * |
|
404 | * @return the value object array or null if not set |
|
405 | */ |
|
406 | protected Object [] getToStringParam(final String name) |
|
407 | { |
|
408 | 2 | if (super.containsKey(name)) |
409 | { |
|
410 | 0 | return getParam(name); |
411 | } |
|
412 | else |
|
413 | { |
|
414 | 2 | return getFileItemParam(name); |
415 | } |
|
416 | } |
|
417 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |