Coverage report

  %line %branch
org.apache.turbine.util.parser.DefaultParameterParser
34% 
92% 

 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.