1 // Copyright (C) 1998-2001 by Jason Hunter <jhunter_AT_acm_DOT_org>. 2 // All rights reserved. Use of this class is limited. 3 // Please see the LICENSE for more information. 4 5 package com.oreilly.servlet; 6 7 import java.io.*; 8 import java.util.*; 9 import javax.servlet.*; 10 11 /** 12 * A class to simplify parameter handling. It can return parameters of 13 * any primitive type (no casting or parsing required), can throw an 14 * exception when a parameter is not found (simplifying error handling), 15 * and can accept default values (eliminating error handling). 16 * <p> 17 * It is used like this: 18 * <blockquote><pre> 19 * ParameterParser parser = new ParameterParser(req); 20 * 21 * float ratio = parser.getFloatParameter("ratio", 1.0); 22 * 23 * int count = 0; 24 * try { 25 * count = parser.getIntParameter("count"); 26 * } 27 * catch (NumberFormatException e) { 28 * handleMalformedCount(); 29 * } 30 * catch (ParameterNotFoundException e) { 31 * handleNoCount(); 32 * } 33 * </pre></blockquote> 34 * 35 * There's also a capability to find out if any required parameters are 36 * missing from a request: 37 * <blockquote><pre> 38 * ParameterParser parser = new ParameterParser(req); 39 * String[] required = { "fname", "lname", "account" }; 40 * String[] missing = parser.getMissingParameters(required); 41 * </pre></blockquote> 42 * 43 * The default charset for input parameters is ISO-8859-1 (Latin-1). 44 * If the parameter values are encoded in another format, specify that using 45 * setCharacterEncoding() before parsing. The parameter names currently 46 * have to be in the Latin-1 character set: 47 * <blockquote><pre> 48 * ParameterParser parser = new ParameterParser(req); 49 * parser.setCharacterEncoding("Shift_JIS"); 50 * String japaneseValue = parser.getStringParameter("latinName"); 51 * </pre></blockquote> 52 * 53 * @see com.oreilly.servlet.ParameterNotFoundException 54 * 55 * @author <b>Jason Hunter</b>, Copyright © 1998, 1999 56 * @version 1.4, 2000/12/14, better checking the selected encoding is valid in 57 * setCharacterEncoding() thanks to Dewayne McNair 58 * @version 1.3, 2000/05/17, added setCharacterEncoding() 59 * @version 1.2, 2000/05/17, getBooleanParameter() now recognizes "on" and "yes" 60 * @version 1.1, 1999/12/20, added getMissingParameters() method 61 * @version 1.0, 1998/09/18 62 */ 63 public class ParameterParser { 64 65 private ServletRequest req; 66 private String encoding; 67 68 /** 69 * Constructs a new ParameterParser to handle the parameters of the 70 * given request. 71 * 72 * @param req the servlet request 73 */ ParameterParser(ServletRequest req)74 public ParameterParser(ServletRequest req) { 75 this.req = req; 76 } 77 78 /** 79 * Sets the character encoding (charset) of the request to help the parser 80 * properly decode parameter values. The default is to return undecoded values, 81 * the same as would be returned by getParameter(). 82 * 83 * @param encoding the charset of the request 84 * @exception UnsupportedEncodingException if the charset is not supported 85 * on this sytem 86 */ setCharacterEncoding(String encoding)87 public void setCharacterEncoding(String encoding) 88 throws UnsupportedEncodingException { 89 // Test the encoding is valid 90 new String("".getBytes("8859_1"), encoding); 91 // Getting here means we're valid, so set the encoding 92 this.encoding = encoding; 93 } 94 95 /** 96 * Gets the named parameter value as a String 97 * 98 * @param name the parameter name 99 * @return the parameter value as a String 100 * @exception ParameterNotFoundException if the parameter was not found 101 * or was the empty string 102 */ getStringParameter(String name)103 public String getStringParameter(String name) 104 throws ParameterNotFoundException { 105 String[] values = req.getParameterValues(name); 106 if (values == null) { 107 throw new ParameterNotFoundException(name + " not found"); 108 } 109 else if (values[0].length() == 0) { 110 throw new ParameterNotFoundException(name + " was empty"); 111 } 112 else { 113 if (encoding == null) { 114 return values[0]; 115 } 116 else { 117 try { 118 return new String(values[0].getBytes("8859_1"), encoding); 119 } 120 catch (UnsupportedEncodingException e) { 121 return values[0]; // should never happen 122 } 123 } 124 } 125 } 126 127 /** 128 * Gets the named parameter value as a String, with a default. 129 * Returns the default value if the parameter is not found or 130 * is the empty string. 131 * 132 * @param name the parameter name 133 * @param def the default parameter value 134 * @return the parameter value as a String, or the default 135 */ getStringParameter(String name, String def)136 public String getStringParameter(String name, String def) { 137 try { return getStringParameter(name); } 138 catch (Exception e) { return def; } 139 } 140 141 /** 142 * Gets the named parameter value as a boolean, with true indicated by 143 * "true", "on", or "yes" in any letter case, false indicated by "false", 144 * "off", or "no" in any letter case. 145 * 146 * @param name the parameter name 147 * @return the parameter value as a boolean 148 * @exception ParameterNotFoundException if the parameter was not found 149 * @exception NumberFormatException if the parameter could not be converted 150 * to a boolean 151 */ getBooleanParameter(String name)152 public boolean getBooleanParameter(String name) 153 throws ParameterNotFoundException, NumberFormatException { 154 String value = getStringParameter(name).toLowerCase(); 155 if ((value.equalsIgnoreCase("true")) || 156 (value.equalsIgnoreCase("on")) || 157 (value.equalsIgnoreCase("yes"))) { 158 return true; 159 } 160 else if ((value.equalsIgnoreCase("false")) || 161 (value.equalsIgnoreCase("off")) || 162 (value.equalsIgnoreCase("no"))) { 163 return false; 164 } 165 else { 166 throw new NumberFormatException("Parameter " + name + " value " + value + 167 " is not a boolean"); 168 } 169 } 170 171 /** 172 * Gets the named parameter value as a boolean, with a default. 173 * Returns the default value if the parameter is not found. 174 * 175 * @param name the parameter name 176 * @param def the default parameter value 177 * @return the parameter value as a boolean, or the default 178 */ getBooleanParameter(String name, boolean def)179 public boolean getBooleanParameter(String name, boolean def) { 180 try { return getBooleanParameter(name); } 181 catch (Exception e) { return def; } 182 } 183 184 /** 185 * Gets the named parameter value as a byte 186 * 187 * @param name the parameter name 188 * @return the parameter value as a byte 189 * @exception ParameterNotFoundException if the parameter was not found 190 * @exception NumberFormatException if the parameter value could not 191 * be converted to a byte 192 */ getByteParameter(String name)193 public byte getByteParameter(String name) 194 throws ParameterNotFoundException, NumberFormatException { 195 return Byte.parseByte(getStringParameter(name)); 196 } 197 198 /** 199 * Gets the named parameter value as a byte, with a default. 200 * Returns the default value if the parameter is not found or cannot 201 * be converted to a byte. 202 * 203 * @param name the parameter name 204 * @param def the default parameter value 205 * @return the parameter value as a byte, or the default 206 */ getByteParameter(String name, byte def)207 public byte getByteParameter(String name, byte def) { 208 try { return getByteParameter(name); } 209 catch (Exception e) { return def; } 210 } 211 212 /** 213 * Gets the named parameter value as a char 214 * 215 * @param name the parameter name 216 * @return the parameter value as a char 217 * @exception ParameterNotFoundException if the parameter was not found 218 * or was the empty string 219 */ getCharParameter(String name)220 public char getCharParameter(String name) 221 throws ParameterNotFoundException { 222 String param = getStringParameter(name); 223 if (param.length() == 0) 224 throw new ParameterNotFoundException(name + " is empty string"); 225 else 226 return (param.charAt(0)); 227 } 228 229 /** 230 * Gets the named parameter value as a char, with a default. 231 * Returns the default value if the parameter is not found. 232 * 233 * @param name the parameter name 234 * @param def the default parameter value 235 * @return the parameter value as a char, or the default 236 */ getCharParameter(String name, char def)237 public char getCharParameter(String name, char def) { 238 try { return getCharParameter(name); } 239 catch (Exception e) { return def; } 240 } 241 242 /** 243 * Gets the named parameter value as a double 244 * 245 * @param name the parameter name 246 * @return the parameter value as a double 247 * @exception ParameterNotFoundException if the parameter was not found 248 * @exception NumberFormatException if the parameter could not be converted 249 * to a double 250 */ getDoubleParameter(String name)251 public double getDoubleParameter(String name) 252 throws ParameterNotFoundException, NumberFormatException { 253 return new Double(getStringParameter(name)).doubleValue(); 254 } 255 256 /** 257 * Gets the named parameter value as a double, with a default. 258 * Returns the default value if the parameter is not found. 259 * 260 * @param name the parameter name 261 * @param def the default parameter value 262 * @return the parameter value as a double, or the default 263 */ getDoubleParameter(String name, double def)264 public double getDoubleParameter(String name, double def) { 265 try { return getDoubleParameter(name); } 266 catch (Exception e) { return def; } 267 } 268 269 /** 270 * Gets the named parameter value as a float 271 * 272 * @param name the parameter name 273 * @return the parameter value as a float 274 * @exception ParameterNotFoundException if the parameter was not found 275 * @exception NumberFormatException if the parameter could not be converted 276 * to a float 277 */ getFloatParameter(String name)278 public float getFloatParameter(String name) 279 throws ParameterNotFoundException, NumberFormatException { 280 return new Float(getStringParameter(name)).floatValue(); 281 } 282 283 /** 284 * Gets the named parameter value as a float, with a default. 285 * Returns the default value if the parameter is not found. 286 * 287 * @param name the parameter name 288 * @param def the default parameter value 289 * @return the parameter value as a float, or the default 290 */ getFloatParameter(String name, float def)291 public float getFloatParameter(String name, float def) { 292 try { return getFloatParameter(name); } 293 catch (Exception e) { return def; } 294 } 295 296 /** 297 * Gets the named parameter value as a int 298 * 299 * @param name the parameter name 300 * @return the parameter value as a int 301 * @exception ParameterNotFoundException if the parameter was not found 302 * @exception NumberFormatException if the parameter could not be converted 303 * to a int 304 */ getIntParameter(String name)305 public int getIntParameter(String name) 306 throws ParameterNotFoundException, NumberFormatException { 307 return Integer.parseInt(getStringParameter(name)); 308 } 309 310 /** 311 * Gets the named parameter value as a int, with a default. 312 * Returns the default value if the parameter is not found. 313 * 314 * @param name the parameter name 315 * @param def the default parameter value 316 * @return the parameter value as a int, or the default 317 */ getIntParameter(String name, int def)318 public int getIntParameter(String name, int def) { 319 try { return getIntParameter(name); } 320 catch (Exception e) { return def; } 321 } 322 323 /** 324 * Gets the named parameter value as a long 325 * 326 * @param name the parameter name 327 * @return the parameter value as a long 328 * @exception ParameterNotFoundException if the parameter was not found 329 * @exception NumberFormatException if the parameter could not be converted 330 * to a long 331 */ getLongParameter(String name)332 public long getLongParameter(String name) 333 throws ParameterNotFoundException, NumberFormatException { 334 return Long.parseLong(getStringParameter(name)); 335 } 336 337 /** 338 * Gets the named parameter value as a long, with a default. 339 * Returns the default value if the parameter is not found. 340 * 341 * @param name the parameter name 342 * @param def the default parameter value 343 * @return the parameter value as a long, or the default 344 */ getLongParameter(String name, long def)345 public long getLongParameter(String name, long def) { 346 try { return getLongParameter(name); } 347 catch (Exception e) { return def; } 348 } 349 350 /** 351 * Gets the named parameter value as a short 352 * 353 * @param name the parameter name 354 * @return the parameter value as a short 355 * @exception ParameterNotFoundException if the parameter was not found 356 * @exception NumberFormatException if the parameter could not be converted 357 * to a short 358 */ getShortParameter(String name)359 public short getShortParameter(String name) 360 throws ParameterNotFoundException, NumberFormatException { 361 return Short.parseShort(getStringParameter(name)); 362 } 363 364 /** 365 * Gets the named parameter value as a short, with a default. 366 * Returns the default value if the parameter is not found. 367 * 368 * @param name the parameter name 369 * @param def the default parameter value 370 * @return the parameter value as a short, or the default 371 */ getShortParameter(String name, short def)372 public short getShortParameter(String name, short def) { 373 try { return getShortParameter(name); } 374 catch (Exception e) { return def; } 375 } 376 377 /** 378 * Determines which of the required parameters were missing from the 379 * request. Returns null if all the parameters are present. 380 * 381 * @param an array of required parameters 382 * @return an array of missing parameters, or null if none are missing 383 */ getMissingParameters(String[] required)384 public String[] getMissingParameters(String[] required) { 385 Vector missing = new Vector(); 386 for (int i = 0; i < required.length; i++) { 387 String val = getStringParameter(required[i], null); 388 if (val == null) { 389 missing.addElement(required[i]); 390 } 391 } 392 if (missing.size() == 0) { 393 return null; 394 } 395 else { 396 String[] ret = new String[missing.size()]; 397 missing.copyInto(ret); 398 return ret; 399 } 400 } 401 } 402