0001: package org.apache.turbine.util.parser;
0002:
0003: /*
0004: * Copyright 2001-2005 The Apache Software Foundation.
0005: *
0006: * Licensed under the Apache License, Version 2.0 (the "License")
0007: * you may not use this file except in compliance with the License.
0008: * You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing, software
0013: * distributed under the License is distributed on an "AS IS" BASIS,
0014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015: * See the License for the specific language governing permissions and
0016: * limitations under the License.
0017: */
0018:
0019: import java.beans.IndexedPropertyDescriptor;
0020: import java.beans.Introspector;
0021: import java.beans.PropertyDescriptor;
0022: import java.io.UnsupportedEncodingException;
0023: import java.lang.reflect.Method;
0024: import java.math.BigDecimal;
0025: import java.text.DateFormat;
0026: import java.text.ParseException;
0027: import java.util.Calendar;
0028: import java.util.Collections;
0029: import java.util.Date;
0030: import java.util.Enumeration;
0031: import java.util.GregorianCalendar;
0032: import java.util.HashMap;
0033: import java.util.Iterator;
0034: import java.util.Map;
0035: import java.util.Set;
0036:
0037: import org.apache.commons.collections.iterators.ArrayIterator;
0038: import org.apache.commons.lang.ArrayUtils;
0039: import org.apache.commons.lang.StringUtils;
0040: import org.apache.commons.logging.Log;
0041: import org.apache.commons.logging.LogFactory;
0042: import org.apache.torque.om.NumberKey;
0043: import org.apache.torque.om.StringKey;
0044: import org.apache.turbine.TurbineConstants;
0045: import org.apache.turbine.util.DateSelector;
0046: import org.apache.turbine.util.TimeSelector;
0047: import org.apache.turbine.util.pool.RecyclableSupport;
0048:
0049: /**
0050: * BaseValueParser is a base class for classes that need to parse
0051: * name/value Parameters, for example GET/POST data or Cookies
0052: * (DefaultParameterParser and DefaultCookieParser).
0053: *
0054: * <p>It can also be used standalone, for an example see DataStreamParser.
0055: *
0056: * <p>NOTE: The name= portion of a name=value pair may be converted
0057: * to lowercase or uppercase when the object is initialized and when
0058: * new data is added. This behaviour is determined by the url.case.folding
0059: * property in TurbineResources.properties. Adding a name/value pair may
0060: * overwrite existing name=value pairs if the names match:
0061: *
0062: * <pre>
0063: * ValueParser vp = new BaseValueParser();
0064: * vp.add("ERROR",1);
0065: * vp.add("eRrOr",2);
0066: * int result = vp.getInt("ERROR");
0067: * </pre>
0068: *
0069: * In the above example, result is 2.
0070: *
0071: * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
0072: * @author <a href="mailto:jon@clearink.com">Jon S. Stevens</a>
0073: * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
0074: * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
0075: * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
0076: * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
0077: * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
0078: * @version $Id: BaseValueParser.java 291608 2005-09-26 12:20:40Z henning $
0079: */
0080: public class BaseValueParser extends RecyclableSupport implements
0081: ValueParser {
0082: /** Logging */
0083: private static Log log = LogFactory.getLog(BaseValueParser.class);
0084:
0085: /**
0086: * Random access storage for parameter data. The keys must always be
0087: * Strings. The values will be arrays of Strings.
0088: */
0089: private Map parameters = new HashMap();
0090:
0091: /** The character encoding to use when converting to byte arrays */
0092: private String characterEncoding = TurbineConstants.PARAMETER_ENCODING_DEFAULT;
0093:
0094: /**
0095: * A static version of the convert method, which
0096: * trims the string data and applies the conversion specified in
0097: * the property given by URL_CASE_FOLDING. It returns a new
0098: * string so that it does not destroy the value data.
0099: *
0100: * @param value A String to be processed.
0101: * @return A new String converted to lowercase and trimmed.
0102: * @deprecated Use ParserUtils.convertAndTrim(value).
0103: */
0104: public static String convertAndTrim(String value) {
0105: return ParserUtils.convertAndTrim(value);
0106: }
0107:
0108: /**
0109: * Default constructor
0110: */
0111: public BaseValueParser() {
0112: this (TurbineConstants.PARAMETER_ENCODING_DEFAULT);
0113: }
0114:
0115: /**
0116: * Constructor that takes a character encoding
0117: */
0118: public BaseValueParser(String characterEncoding) {
0119: super ();
0120: setCharacterEncoding(characterEncoding);
0121: }
0122:
0123: /**
0124: * Recycles the parser with a character encoding.
0125: *
0126: * @param characterEncoding the character encoding.
0127: *
0128: * @todo Is this method used anywhere? Does it make any sense at all?
0129: */
0130: public void recycle(String characterEncoding) {
0131: setCharacterEncoding(characterEncoding);
0132: super .recycle();
0133: }
0134:
0135: /**
0136: * Disposes the parser.
0137: */
0138: public void dispose() {
0139: clear();
0140: super .dispose();
0141: }
0142:
0143: /**
0144: * Clear all name/value pairs out of this object.
0145: */
0146: public void clear() {
0147: parameters.clear();
0148: }
0149:
0150: /**
0151: * Set the character encoding that will be used by this ValueParser.
0152: */
0153: public void setCharacterEncoding(String s) {
0154: characterEncoding = s;
0155: }
0156:
0157: /**
0158: * Get the character encoding that will be used by this ValueParser.
0159: */
0160: public String getCharacterEncoding() {
0161: return characterEncoding;
0162: }
0163:
0164: /**
0165: * Add a name/value pair into this object.
0166: *
0167: * @param name A String with the name.
0168: * @param value A double with the value.
0169: */
0170: public void add(String name, double value) {
0171: add(name, Double.toString(value));
0172: }
0173:
0174: /**
0175: * Add a name/value pair into this object.
0176: *
0177: * @param name A String with the name.
0178: * @param value An int with the value.
0179: */
0180: public void add(String name, int value) {
0181: add(name, Integer.toString(value));
0182: }
0183:
0184: /**
0185: * Add a name/value pair into this object.
0186: *
0187: * @param name A String with the name.
0188: * @param value An Integer with the value.
0189: */
0190: public void add(String name, Integer value) {
0191: if (value != null) {
0192: add(name, value.toString());
0193: }
0194: }
0195:
0196: /**
0197: * Add a name/value pair into this object.
0198: *
0199: * @param name A String with the name.
0200: * @param value A long with the value.
0201: */
0202: public void add(String name, long value) {
0203: add(name, Long.toString(value));
0204: }
0205:
0206: /**
0207: * Add a name/value pair into this object.
0208: *
0209: * @param name A String with the name.
0210: * @param value A long with the value.
0211: */
0212: public void add(String name, String value) {
0213: if (value != null) {
0214: String[] items = getParam(name);
0215: items = (String[]) ArrayUtils.add(items, value);
0216: putParam(name, items);
0217: }
0218: }
0219:
0220: /**
0221: * Add an array of Strings for a key. This
0222: * is simply adding all the elements in the
0223: * array one by one.
0224: *
0225: * @param name A String with the name.
0226: * @param value A String Array.
0227: */
0228: public void add(String name, String[] value) {
0229: // ArrayUtils.addAll() looks promising but it would also add
0230: // null values into the parameters array, so we can't use that.
0231: if (value != null) {
0232: for (int i = 0; i < value.length; i++) {
0233: if (value[i] != null) {
0234: add(name, value[i]);
0235: }
0236: }
0237: }
0238: }
0239:
0240: /**
0241: * Add a String parameters. If there are any Strings already
0242: * associated with the name, append to the array. This is used
0243: * for handling parameters from multipart POST requests.
0244: *
0245: * @param name A String with the name.
0246: * @param value A String with the value.
0247: *
0248: * @deprecated Use add(name, value) instead.
0249: */
0250: public void append(String name, String value) {
0251: add(name, value);
0252: }
0253:
0254: /**
0255: * Removes the named parameter from the contained hashtable. Wraps to the
0256: * contained <code>Map.remove()</code>.
0257: *
0258: * @return The value that was mapped to the key (a <code>String[]</code>)
0259: * or <code>null</code> if the key was not mapped.
0260: */
0261: public Object remove(String name) {
0262: return parameters.remove(convert(name));
0263: }
0264:
0265: /**
0266: * Trims the string data and applies the conversion specified in
0267: * the property given by URL_CASE_FOLDING. It returns a new
0268: * string so that it does not destroy the value data.
0269: *
0270: * @param value A String to be processed.
0271: * @return A new String converted to lowercase and trimmed.
0272: */
0273: public String convert(String value) {
0274: return ParserUtils.convertAndTrim(value);
0275: }
0276:
0277: /**
0278: * Determine whether a given key has been inserted. All keys are
0279: * stored in lowercase strings, so override method to account for
0280: * this.
0281: *
0282: * @param key An Object with the key to search for.
0283: * @return True if the object is found.
0284: */
0285: public boolean containsKey(Object key) {
0286: return parameters.containsKey(convert(String.valueOf(key)));
0287: }
0288:
0289: /**
0290: * Check for existence of key_day, key_month and key_year
0291: * parameters (as returned by DateSelector generated HTML).
0292: *
0293: * @param key A String with the selector name.
0294: * @return True if keys are found.
0295: */
0296: public boolean containsDateSelectorKeys(String key) {
0297: return (containsKey(key + DateSelector.DAY_SUFFIX)
0298: && containsKey(key + DateSelector.MONTH_SUFFIX) && containsKey(key
0299: + DateSelector.YEAR_SUFFIX));
0300: }
0301:
0302: /**
0303: * Check for existence of key_hour, key_minute and key_second
0304: * parameters (as returned by TimeSelector generated HTML).
0305: *
0306: * @param key A String with the selector name.
0307: * @return True if keys are found.
0308: */
0309: public boolean containsTimeSelectorKeys(String key) {
0310: return (containsKey(key + TimeSelector.HOUR_SUFFIX)
0311: && containsKey(key + TimeSelector.MINUTE_SUFFIX) && containsKey(key
0312: + TimeSelector.SECOND_SUFFIX));
0313: }
0314:
0315: /**
0316: * Get an enumerator for the parameter keys.
0317: *
0318: * @return An <code>enumerator</code> of the keys.
0319: * @deprecated use {@link #keySet} instead.
0320: */
0321: public Enumeration keys() {
0322: return Collections.enumeration(keySet());
0323: }
0324:
0325: /**
0326: * Gets the set of keys
0327: *
0328: * @return A <code>Set</code> of the keys.
0329: */
0330: public Set keySet() {
0331: return parameters.keySet();
0332: }
0333:
0334: /**
0335: * Returns all the available parameter names.
0336: *
0337: * @return A object array with the keys.
0338: */
0339: public Object[] getKeys() {
0340: return keySet().toArray();
0341: }
0342:
0343: /**
0344: * Return a boolean for the given name. If the name does not
0345: * exist, return defaultValue.
0346: *
0347: * @param name A String with the name.
0348: * @param defaultValue The default value.
0349: * @return A boolean.
0350: */
0351: public boolean getBoolean(String name, boolean defaultValue) {
0352: Boolean result = getBooleanObject(name);
0353: return (result == null ? defaultValue : result.booleanValue());
0354: }
0355:
0356: /**
0357: * Return a boolean for the given name. If the name does not
0358: * exist, return false.
0359: *
0360: * @param name A String with the name.
0361: * @return A boolean.
0362: */
0363: public boolean getBoolean(String name) {
0364: return getBoolean(name, false);
0365: }
0366:
0367: /**
0368: * Returns a Boolean object for the given name. If the parameter
0369: * does not exist or can not be parsed as a boolean, null is returned.
0370: * <p>
0371: * Valid values for true: true, on, 1, yes<br>
0372: * Valid values for false: false, off, 0, no<br>
0373: * <p>
0374: * The string is compared without reguard to case.
0375: *
0376: * @param name A String with the name.
0377: * @return A Boolean.
0378: */
0379: public Boolean getBooleanObject(String name) {
0380: Boolean result = null;
0381: String value = getString(name);
0382:
0383: if (StringUtils.isNotEmpty(value)) {
0384: if (value.equals("1") || value.equalsIgnoreCase("true")
0385: || value.equalsIgnoreCase("yes")
0386: || value.equalsIgnoreCase("on")) {
0387: result = Boolean.TRUE;
0388: } else if (value.equals("0")
0389: || value.equalsIgnoreCase("false")
0390: || value.equalsIgnoreCase("no")
0391: || value.equalsIgnoreCase("off")) {
0392: result = Boolean.FALSE;
0393: } else {
0394: logConvertionFailure(name, value, "Boolean");
0395: }
0396: }
0397: return result;
0398: }
0399:
0400: /**
0401: * Returns a Boolean object for the given name. If the parameter
0402: * does not exist or can not be parsed as a boolean, null is returned.
0403: * <p>
0404: * Valid values for true: true, on, 1, yes<br>
0405: * Valid values for false: false, off, 0, no<br>
0406: * <p>
0407: * The string is compared without reguard to case.
0408: *
0409: * @param name A String with the name.
0410: * @param defaultValue The default value.
0411: * @return A Boolean.
0412: */
0413: public Boolean getBooleanObject(String name, Boolean defaultValue) {
0414: Boolean result = getBooleanObject(name);
0415: return (result == null ? defaultValue : result);
0416: }
0417:
0418: /**
0419: * Return a Boolean for the given name. If the name does not
0420: * exist, return defaultValue.
0421: *
0422: * @param name A String with the name.
0423: * @param defaultValue The default value.
0424: * @return A Boolean.
0425: * @deprecated use {@link #getBooleanObject} instead
0426: */
0427: public Boolean getBool(String name, boolean defaultValue) {
0428: // JDK 1.3 has no Boolean.valueOf(boolean)
0429: return getBooleanObject(name, new Boolean(defaultValue));
0430: }
0431:
0432: /**
0433: * Return a Boolean for the given name. If the name does not
0434: * exist, return false.
0435: *
0436: * @param name A String with the name.
0437: * @return A Boolean.
0438: * @deprecated use {@link #getBooleanObject(String)} instead
0439: */
0440: public Boolean getBool(String name) {
0441: return getBooleanObject(name, Boolean.FALSE);
0442: }
0443:
0444: /**
0445: * Return a double for the given name. If the name does not
0446: * exist, return defaultValue.
0447: *
0448: * @param name A String with the name.
0449: * @param defaultValue The default value.
0450: * @return A double.
0451: */
0452: public double getDouble(String name, double defaultValue) {
0453: double result = defaultValue;
0454: String value = getString(name);
0455:
0456: if (StringUtils.isNotEmpty(value)) {
0457: try {
0458: result = Double.parseDouble(StringUtils.trim(value));
0459: } catch (NumberFormatException e) {
0460: logConvertionFailure(name, value, "Double");
0461: }
0462: }
0463: return result;
0464: }
0465:
0466: /**
0467: * Return a double for the given name. If the name does not
0468: * exist, return 0.0.
0469: *
0470: * @param name A String with the name.
0471: * @return A double.
0472: */
0473: public double getDouble(String name) {
0474: return getDouble(name, 0.0);
0475: }
0476:
0477: /**
0478: * Return an array of doubles for the given name. If the name does
0479: * not exist, return null.
0480: *
0481: * @param name A String with the name.
0482: * @return A double[].
0483: */
0484: public double[] getDoubles(String name) {
0485: double[] result = null;
0486: String value[] = getParam(name);
0487: if (value != null) {
0488: result = new double[value.length];
0489: for (int i = 0; i < value.length; i++) {
0490: if (StringUtils.isNotEmpty(value[i])) {
0491: try {
0492: result[i] = Double.parseDouble(value[i]);
0493: } catch (NumberFormatException e) {
0494: logConvertionFailure(name, value[i], "Double");
0495: }
0496: }
0497: }
0498: }
0499: return result;
0500: }
0501:
0502: /**
0503: * Return a Double for the given name. If the name does not
0504: * exist, return defaultValue.
0505: *
0506: * @param name A String with the name.
0507: * @param defaultValue The default value.
0508: * @return A double.
0509: */
0510: public Double getDoubleObject(String name, Double defaultValue) {
0511: Double result = getDoubleObject(name);
0512: return (result == null ? defaultValue : result);
0513: }
0514:
0515: /**
0516: * Return a Double for the given name. If the name does not
0517: * exist, return null.
0518: *
0519: * @param name A String with the name.
0520: * @return A double.
0521: */
0522: public Double getDoubleObject(String name) {
0523: Double result = null;
0524: String value = getString(name);
0525:
0526: if (StringUtils.isNotEmpty(value)) {
0527: try {
0528: result = new Double(StringUtils.trim(value));
0529: } catch (NumberFormatException e) {
0530: logConvertionFailure(name, value, "Double");
0531: }
0532: }
0533: return result;
0534: }
0535:
0536: /**
0537: * Return an array of doubles for the given name. If the name does
0538: * not exist, return null.
0539: *
0540: * @param name A String with the name.
0541: * @return A double[].
0542: */
0543: public Double[] getDoubleObjects(String name) {
0544: Double[] result = null;
0545: String value[] = getParam(name);
0546: if (value != null) {
0547: result = new Double[value.length];
0548: for (int i = 0; i < value.length; i++) {
0549: if (StringUtils.isNotEmpty(value[i])) {
0550: try {
0551: result[i] = Double.valueOf(value[i]);
0552: } catch (NumberFormatException e) {
0553: logConvertionFailure(name, value[i], "Double");
0554: }
0555: }
0556: }
0557: }
0558: return result;
0559: }
0560:
0561: /**
0562: * Return a float for the given name. If the name does not
0563: * exist, return defaultValue.
0564: *
0565: * @param name A String with the name.
0566: * @param defaultValue The default value.
0567: * @return A float.
0568: */
0569: public float getFloat(String name, float defaultValue) {
0570: float result = defaultValue;
0571: String value = getString(name);
0572:
0573: if (StringUtils.isNotEmpty(value)) {
0574: try {
0575: result = Float.parseFloat(StringUtils.trim(value));
0576: } catch (NumberFormatException e) {
0577: logConvertionFailure(name, value, "Float");
0578: }
0579: }
0580: return result;
0581: }
0582:
0583: /**
0584: * Return a float for the given name. If the name does not
0585: * exist, return 0.0.
0586: *
0587: * @param name A String with the name.
0588: * @return A float.
0589: */
0590: public float getFloat(String name) {
0591: return getFloat(name, 0.0f);
0592: }
0593:
0594: /**
0595: * Return an array of floats for the given name. If the name does
0596: * not exist, return null.
0597: *
0598: * @param name A String with the name.
0599: * @return A float[].
0600: */
0601: public float[] getFloats(String name) {
0602: float[] result = null;
0603: String value[] = getParam(name);
0604: if (value != null) {
0605: result = new float[value.length];
0606: for (int i = 0; i < value.length; i++) {
0607: if (StringUtils.isNotEmpty(value[i])) {
0608: try {
0609: result[i] = Float.parseFloat(value[i]);
0610: } catch (NumberFormatException e) {
0611: logConvertionFailure(name, value[i], "Float");
0612: }
0613: }
0614: }
0615: }
0616: return result;
0617: }
0618:
0619: /**
0620: * Return a Float for the given name. If the name does not
0621: * exist, return defaultValue.
0622: *
0623: * @param name A String with the name.
0624: * @param defaultValue The default value.
0625: * @return A Float.
0626: */
0627: public Float getFloatObject(String name, Float defaultValue) {
0628: Float result = getFloatObject(name);
0629: return (result == null ? defaultValue : result);
0630: }
0631:
0632: /**
0633: * Return a float for the given name. If the name does not
0634: * exist, return null.
0635: *
0636: * @param name A String with the name.
0637: * @return A Float.
0638: */
0639: public Float getFloatObject(String name) {
0640: Float result = null;
0641: String value = getString(name);
0642:
0643: if (StringUtils.isNotEmpty(value)) {
0644: try {
0645: result = new Float(StringUtils.trim(value));
0646: } catch (NumberFormatException e) {
0647: logConvertionFailure(name, value, "Float");
0648: }
0649: }
0650:
0651: return result;
0652: }
0653:
0654: /**
0655: * Return an array of floats for the given name. If the name does
0656: * not exist, return null.
0657: *
0658: * @param name A String with the name.
0659: * @return A float[].
0660: */
0661: public Float[] getFloatObjects(String name) {
0662: Float[] result = null;
0663: String value[] = getParam(name);
0664: if (value != null) {
0665: result = new Float[value.length];
0666: for (int i = 0; i < value.length; i++) {
0667: if (StringUtils.isNotEmpty(value[i])) {
0668: try {
0669: result[i] = Float.valueOf(value[i]);
0670: } catch (NumberFormatException e) {
0671: logConvertionFailure(name, value[i], "Float");
0672: }
0673: }
0674: }
0675: }
0676: return result;
0677: }
0678:
0679: /**
0680: * Return a BigDecimal for the given name. If the name does not
0681: * exist, return defaultValue.
0682: *
0683: * @param name A String with the name.
0684: * @param defaultValue The default value.
0685: * @return A BigDecimal.
0686: */
0687: public BigDecimal getBigDecimal(String name, BigDecimal defaultValue) {
0688: BigDecimal result = defaultValue;
0689: String value = getString(name);
0690:
0691: if (StringUtils.isNotEmpty(value)) {
0692: try {
0693: result = new BigDecimal(StringUtils.trim(value));
0694: } catch (NumberFormatException e) {
0695: logConvertionFailure(name, value, "BigDecimal");
0696: }
0697: }
0698:
0699: return result;
0700: }
0701:
0702: /**
0703: * Return a BigDecimal for the given name. If the name does not
0704: * exist, return 0.0.
0705: *
0706: * @param name A String with the name.
0707: * @return A BigDecimal.
0708: */
0709: public BigDecimal getBigDecimal(String name) {
0710: return getBigDecimal(name, new BigDecimal(0.0));
0711: }
0712:
0713: /**
0714: * Return an array of BigDecimals for the given name. If the name
0715: * does not exist, return null.
0716: *
0717: * @param name A String with the name.
0718: * @return A BigDecimal[].
0719: */
0720: public BigDecimal[] getBigDecimals(String name) {
0721: BigDecimal[] result = null;
0722: String value[] = getParam(name);
0723: if (value != null) {
0724: result = new BigDecimal[value.length];
0725: for (int i = 0; i < value.length; i++) {
0726: if (StringUtils.isNotEmpty(value[i])) {
0727: try {
0728: result[i] = new BigDecimal(value[i]);
0729: } catch (NumberFormatException e) {
0730: logConvertionFailure(name, value[i],
0731: "BigDecimal");
0732: }
0733: }
0734: }
0735: }
0736: return result;
0737: }
0738:
0739: /**
0740: * Return an int for the given name. If the name does not exist,
0741: * return defaultValue.
0742: *
0743: * @param name A String with the name.
0744: * @param defaultValue The default value.
0745: * @return An int.
0746: */
0747: public int getInt(String name, int defaultValue) {
0748: int result = defaultValue;
0749: String value = getString(name);
0750:
0751: if (StringUtils.isNotEmpty(value)) {
0752: try {
0753: result = Integer.parseInt(StringUtils.trim(value));
0754: } catch (NumberFormatException e) {
0755: logConvertionFailure(name, value, "Integer");
0756: }
0757: }
0758:
0759: return result;
0760: }
0761:
0762: /**
0763: * Return an int for the given name. If the name does not exist,
0764: * return 0.
0765: *
0766: * @param name A String with the name.
0767: * @return An int.
0768: */
0769: public int getInt(String name) {
0770: return getInt(name, 0);
0771: }
0772:
0773: /**
0774: * Return an Integer for the given name. If the name does not
0775: * exist, return defaultValue.
0776: *
0777: * @param name A String with the name.
0778: * @param defaultValue The default value.
0779: * @return An Integer.
0780: * @deprecated use {@link #getIntObject} instead
0781: */
0782: public Integer getInteger(String name, int defaultValue) {
0783: return getIntObject(name, new Integer(defaultValue));
0784: }
0785:
0786: /**
0787: * Return an Integer for the given name. If the name does not
0788: * exist, return defaultValue. You cannot pass in a null here for
0789: * the default value.
0790: *
0791: * @param name A String with the name.
0792: * @param def The default value.
0793: * @return An Integer.
0794: * @deprecated use {@link #getIntObject} instead
0795: */
0796: public Integer getInteger(String name, Integer def) {
0797: return getIntObject(name, def);
0798: }
0799:
0800: /**
0801: * Return an Integer for the given name. If the name does not
0802: * exist, return 0.
0803: *
0804: * @param name A String with the name.
0805: * @return An Integer.
0806: * @deprecated use {@link #getIntObject} instead
0807: */
0808: public Integer getInteger(String name) {
0809: return getIntObject(name, new Integer(0));
0810: }
0811:
0812: /**
0813: * Return an array of ints for the given name. If the name does
0814: * not exist, return null.
0815: *
0816: * @param name A String with the name.
0817: * @return An int[].
0818: */
0819: public int[] getInts(String name) {
0820: int[] result = null;
0821: String value[] = getParam(name);
0822: if (value != null) {
0823: result = new int[value.length];
0824: for (int i = 0; i < value.length; i++) {
0825: if (StringUtils.isNotEmpty(value[i])) {
0826: try {
0827: result[i] = Integer.parseInt(value[i]);
0828: } catch (NumberFormatException e) {
0829: logConvertionFailure(name, value[i], "Integer");
0830: }
0831: }
0832: }
0833: }
0834: return result;
0835: }
0836:
0837: /**
0838: * Return an Integer for the given name. If the name does not exist,
0839: * return defaultValue.
0840: *
0841: * @param name A String with the name.
0842: * @param defaultValue The default value.
0843: * @return An Integer.
0844: */
0845: public Integer getIntObject(String name, Integer defaultValue) {
0846: Integer result = getIntObject(name);
0847: return (result == null ? defaultValue : result);
0848: }
0849:
0850: /**
0851: * Return an Integer for the given name. If the name does not exist,
0852: * return null.
0853: *
0854: * @param name A String with the name.
0855: * @return An Integer.
0856: */
0857: public Integer getIntObject(String name) {
0858: Integer result = null;
0859: String value = getString(name);
0860:
0861: if (StringUtils.isNotEmpty(value)) {
0862: try {
0863: result = new Integer(StringUtils.trim(value));
0864: } catch (NumberFormatException e) {
0865: logConvertionFailure(name, value, "Integer");
0866: }
0867: }
0868:
0869: return result;
0870: }
0871:
0872: /**
0873: * Return an array of Integers for the given name. If the name
0874: * does not exist, return null.
0875: *
0876: * @param name A String with the name.
0877: * @return An Integer[].
0878: */
0879: public Integer[] getIntObjects(String name) {
0880: Integer[] result = null;
0881: String value[] = getParam(name);
0882: if (value != null) {
0883: result = new Integer[value.length];
0884: for (int i = 0; i < value.length; i++) {
0885: if (StringUtils.isNotEmpty(value[i])) {
0886: try {
0887: result[i] = Integer.valueOf(value[i]);
0888: } catch (NumberFormatException e) {
0889: logConvertionFailure(name, value[i], "Integer");
0890: }
0891: }
0892: }
0893: }
0894: return result;
0895: }
0896:
0897: /**
0898: * Return an array of Integers for the given name. If the name
0899: * does not exist, return null.
0900: *
0901: * @param name A String with the name.
0902: * @return An Integer[].
0903: * @deprecated use {@link #getIntObjects} instead
0904: */
0905: public Integer[] getIntegers(String name) {
0906: return getIntObjects(name);
0907: }
0908:
0909: /**
0910: * Return a long for the given name. If the name does not exist,
0911: * return defaultValue.
0912: *
0913: * @param name A String with the name.
0914: * @param defaultValue The default value.
0915: * @return A long.
0916: */
0917: public long getLong(String name, long defaultValue) {
0918: long result = defaultValue;
0919: String value = getString(name);
0920:
0921: if (StringUtils.isNotEmpty(value)) {
0922: try {
0923: result = Long.parseLong(StringUtils.trim(value));
0924: } catch (NumberFormatException e) {
0925: logConvertionFailure(name, value, "Long");
0926: }
0927: }
0928:
0929: return result;
0930: }
0931:
0932: /**
0933: * Return a long for the given name. If the name does not exist,
0934: * return 0.
0935: *
0936: * @param name A String with the name.
0937: * @return A long.
0938: */
0939: public long getLong(String name) {
0940: return getLong(name, 0);
0941: }
0942:
0943: /**
0944: * Return an array of longs for the given name. If the name does
0945: * not exist, return null.
0946: *
0947: * @param name A String with the name.
0948: * @return A long[].
0949: */
0950: public long[] getLongs(String name) {
0951: long[] result = null;
0952: String value[] = getParam(name);
0953: if (value != null) {
0954: result = new long[value.length];
0955: for (int i = 0; i < value.length; i++) {
0956: if (StringUtils.isNotEmpty(value[i])) {
0957: try {
0958: result[i] = Long.parseLong(value[i]);
0959: } catch (NumberFormatException e) {
0960: logConvertionFailure(name, value[i], "Long");
0961: }
0962: }
0963: }
0964: }
0965: return result;
0966: }
0967:
0968: /**
0969: * Return an array of Longs for the given name. If the name does
0970: * not exist, return null.
0971: *
0972: * @param name A String with the name.
0973: * @return A Long[].
0974: */
0975: public Long[] getLongObjects(String name) {
0976: Long[] result = null;
0977: String value[] = getParam(name);
0978: if (value != null) {
0979: result = new Long[value.length];
0980: for (int i = 0; i < value.length; i++) {
0981: if (StringUtils.isNotEmpty(value[i])) {
0982: try {
0983: result[i] = Long.valueOf(value[i]);
0984: } catch (NumberFormatException e) {
0985: logConvertionFailure(name, value[i], "Long");
0986: }
0987: }
0988: }
0989: }
0990: return result;
0991: }
0992:
0993: /**
0994: * Return a Long for the given name. If the name does
0995: * not exist, return null.
0996: *
0997: * @param name A String with the name.
0998: * @return A Long.
0999: */
1000: public Long getLongObject(String name) {
1001: Long result = null;
1002: String value = getString(name);
1003:
1004: if (StringUtils.isNotEmpty(value)) {
1005: try {
1006: result = new Long(StringUtils.trim(value));
1007: } catch (NumberFormatException e) {
1008: logConvertionFailure(name, value, "Long");
1009: }
1010: }
1011:
1012: return result;
1013: }
1014:
1015: /**
1016: * Return a Long for the given name. If the name does
1017: * not exist, return the default value.
1018: *
1019: * @param name A String with the name.
1020: * @param defaultValue The default value.
1021: * @return A Long.
1022: */
1023: public Long getLongObject(String name, Long defaultValue) {
1024: Long result = getLongObject(name);
1025: return (result == null ? defaultValue : result);
1026: }
1027:
1028: /**
1029: * Return a byte for the given name. If the name does not exist,
1030: * return defaultValue.
1031: *
1032: * @param name A String with the name.
1033: * @param defaultValue The default value.
1034: * @return A byte.
1035: */
1036: public byte getByte(String name, byte defaultValue) {
1037: byte result = defaultValue;
1038: String value = getString(name);
1039:
1040: if (StringUtils.isNotEmpty(value)) {
1041: try {
1042: result = Byte.parseByte(StringUtils.trim(value));
1043: } catch (NumberFormatException e) {
1044: logConvertionFailure(name, value, "Byte");
1045: }
1046: }
1047:
1048: return result;
1049: }
1050:
1051: /**
1052: * Return a byte for the given name. If the name does not exist,
1053: * return 0.
1054: *
1055: * @param name A String with the name.
1056: * @return A byte.
1057: */
1058: public byte getByte(String name) {
1059: return getByte(name, (byte) 0);
1060: }
1061:
1062: /**
1063: * Return an array of bytes for the given name. If the name does
1064: * not exist, return null. The array is returned according to the
1065: * HttpRequest's character encoding.
1066: *
1067: * @param name A String with the name.
1068: * @return A byte[].
1069: * @exception UnsupportedEncodingException
1070: */
1071: public byte[] getBytes(String name)
1072: throws UnsupportedEncodingException {
1073: byte result[] = null;
1074: String value = getString(name);
1075: if (value != null) {
1076: result = value.getBytes(getCharacterEncoding());
1077: }
1078: return result;
1079: }
1080:
1081: /**
1082: * Return a byte for the given name. If the name does not exist,
1083: * return defaultValue.
1084: *
1085: * @param name A String with the name.
1086: * @param defaultValue The default value.
1087: * @return A byte.
1088: */
1089: public Byte getByteObject(String name, Byte defaultValue) {
1090: Byte result = getByteObject(name);
1091: return (result == null ? defaultValue : result);
1092: }
1093:
1094: /**
1095: * Return a byte for the given name. If the name does not exist,
1096: * return 0.
1097: *
1098: * @param name A String with the name.
1099: * @return A byte.
1100: */
1101: public Byte getByteObject(String name) {
1102: Byte result = null;
1103: String value = getString(name);
1104:
1105: if (StringUtils.isNotEmpty(value)) {
1106: try {
1107: result = new Byte(StringUtils.trim(value));
1108: } catch (NumberFormatException e) {
1109: logConvertionFailure(name, value, "Byte");
1110: }
1111: }
1112:
1113: return result;
1114: }
1115:
1116: /**
1117: * Return a String for the given name. If the name does not
1118: * exist, return null.
1119: *
1120: * @param name A String with the name.
1121: * @return A String or null if the key is unknown.
1122: */
1123: public String getString(String name) {
1124: String[] value = getParam(name);
1125:
1126: return (value == null || value.length == 0) ? null : value[0];
1127: }
1128:
1129: /**
1130: * Return a String for the given name. If the name does not
1131: * exist, return null. It is the same as the getString() method
1132: * however has been added for simplicity when working with
1133: * template tools such as Velocity which allow you to do
1134: * something like this:
1135: *
1136: * <code>$data.Parameters.form_variable_name</code>
1137: *
1138: * @param name A String with the name.
1139: * @return A String.
1140: */
1141: public String get(String name) {
1142: return getString(name);
1143: }
1144:
1145: /**
1146: * Return a String for the given name. If the name does not
1147: * exist, return the defaultValue.
1148: *
1149: * @param name A String with the name.
1150: * @param defaultValue The default value.
1151: * @return A String.
1152: */
1153: public String getString(String name, String defaultValue) {
1154: String value = getString(name);
1155:
1156: return (StringUtils.isEmpty(value) ? defaultValue : value);
1157: }
1158:
1159: /**
1160: * Set a parameter to a specific value.
1161: *
1162: * This is useful if you want your action to override the values
1163: * of the parameters for the screen to use.
1164: * @param name The name of the parameter.
1165: * @param value The value to set.
1166: */
1167: public void setString(String name, String value) {
1168: if (value != null) {
1169: putParam(name, new String[] { value });
1170: }
1171: }
1172:
1173: /**
1174: * Return an array of Strings for the given name. If the name
1175: * does not exist, return null.
1176: *
1177: * @param name A String with the name.
1178: * @return A String[].
1179: */
1180: public String[] getStrings(String name) {
1181: return getParam(name);
1182: }
1183:
1184: /**
1185: * Return an array of Strings for the given name. If the name
1186: * does not exist, return the defaultValue.
1187: *
1188: * @param name A String with the name.
1189: * @param defaultValue The default value.
1190: * @return A String[].
1191: */
1192: public String[] getStrings(String name, String[] defaultValue) {
1193: String[] value = getParam(name);
1194:
1195: return (value == null || value.length == 0) ? defaultValue
1196: : value;
1197: }
1198:
1199: /**
1200: * Set a parameter to a specific value.
1201: *
1202: * This is useful if you want your action to override the values
1203: * of the parameters for the screen to use.
1204: * @param name The name of the parameter.
1205: * @param values The value to set.
1206: */
1207: public void setStrings(String name, String[] values) {
1208: if (values != null) {
1209: putParam(name, values);
1210: }
1211: }
1212:
1213: /**
1214: * Return an Object for the given name. If the name does not
1215: * exist, return null.
1216: *
1217: * @param name A String with the name.
1218: * @return An Object.
1219: */
1220: public Object getObject(String name) {
1221: return getString(name);
1222: }
1223:
1224: /**
1225: * Return an array of Objects for the given name. If the name
1226: * does not exist, return null.
1227: *
1228: * @param name A String with the name.
1229: * @return An Object[].
1230: */
1231: public Object[] getObjects(String name) {
1232: return getParam(name);
1233: }
1234:
1235: /**
1236: * Returns a {@link java.util.Date} object. String is parsed by supplied
1237: * DateFormat. If the name does not exist or the value could not be
1238: * parsed into a date return the defaultValue.
1239: *
1240: * @param name A String with the name.
1241: * @param df A DateFormat.
1242: * @param defaultValue The default value.
1243: * @return A Date.
1244: */
1245: public Date getDate(String name, DateFormat df, Date defaultValue) {
1246: Date result = defaultValue;
1247: String value = getString(name);
1248:
1249: if (StringUtils.isNotEmpty(value)) {
1250: try {
1251: // Reject invalid dates.
1252: df.setLenient(false);
1253: result = df.parse(value);
1254: } catch (ParseException e) {
1255: logConvertionFailure(name, value, "Date");
1256: }
1257: }
1258:
1259: return result;
1260: }
1261:
1262: /**
1263: * Returns a {@link java.util.Date} object. If there are DateSelector or
1264: * TimeSelector style parameters then these are used. If not and there
1265: * is a parameter 'name' then this is parsed by DateFormat. If the
1266: * name does not exist, return null.
1267: *
1268: * @param name A String with the name.
1269: * @return A Date.
1270: */
1271: public Date getDate(String name) {
1272: Date date = null;
1273:
1274: if (containsDateSelectorKeys(name)) {
1275: try {
1276: Calendar cal = new GregorianCalendar(getInt(name
1277: + DateSelector.YEAR_SUFFIX), getInt(name
1278: + DateSelector.MONTH_SUFFIX), getInt(name
1279: + DateSelector.DAY_SUFFIX));
1280:
1281: // Reject invalid dates.
1282: cal.setLenient(false);
1283: date = cal.getTime();
1284: } catch (IllegalArgumentException e) {
1285: logConvertionFailure(name, "n/a", "Date");
1286: }
1287: } else if (containsTimeSelectorKeys(name)) {
1288: try {
1289: String ampm = getString(name + TimeSelector.AMPM_SUFFIX);
1290: int hour = getInt(name + TimeSelector.HOUR_SUFFIX);
1291:
1292: // Convert from 12 to 24hr format if appropriate
1293: if (ampm != null) {
1294: if (hour == 12) {
1295: hour = (Integer.parseInt(ampm) == Calendar.PM) ? 12
1296: : 0;
1297: } else if (Integer.parseInt(ampm) == Calendar.PM) {
1298: hour += 12;
1299: }
1300: }
1301: Calendar cal = new GregorianCalendar(1, 1, 1, hour,
1302: getInt(name + TimeSelector.MINUTE_SUFFIX),
1303: getInt(name + TimeSelector.SECOND_SUFFIX));
1304:
1305: // Reject invalid dates.
1306: cal.setLenient(false);
1307: date = cal.getTime();
1308: } catch (IllegalArgumentException e) {
1309: logConvertionFailure(name, "n/a", "Date");
1310: }
1311: } else {
1312: DateFormat df = DateFormat.getDateInstance();
1313: date = getDate(name, df, null);
1314: }
1315:
1316: return date;
1317: }
1318:
1319: /**
1320: * Returns a {@link java.util.Date} object. String is parsed by supplied
1321: * DateFormat. If the name does not exist, return null.
1322: *
1323: * @param name A String with the name.
1324: * @param df A DateFormat.
1325: * @return A Date.
1326: */
1327: public Date getDate(String name, DateFormat df) {
1328: return getDate(name, df, null);
1329: }
1330:
1331: /**
1332: * Return an NumberKey for the given name. If the name does not
1333: * exist, return null.
1334: *
1335: * @param name A String with the name.
1336: * @return A NumberKey, or <code>null</code> if unparsable.
1337: * @deprecated no replacement
1338: */
1339: public NumberKey getNumberKey(String name) {
1340: NumberKey result = null;
1341: try {
1342: String value = getString(name);
1343: if (StringUtils.isNotEmpty(value)) {
1344: result = new NumberKey(value);
1345: }
1346: } catch (ClassCastException e) {
1347: log.error("Parameter (" + name
1348: + ") could not be converted to a NumberKey", e);
1349: }
1350: return result;
1351: }
1352:
1353: /**
1354: * Return an StringKey for the given name. If the name does not
1355: * exist, return null.
1356: *
1357: * @param name A String with the name.
1358: * @return A StringKey, or <code>null</code> if unparsable.
1359: * @deprecated no replacement
1360: */
1361: public StringKey getStringKey(String name) {
1362: StringKey result = null;
1363: try {
1364: String value = getString(name);
1365: if (StringUtils.isNotEmpty(value)) {
1366: result = new StringKey(value);
1367: }
1368: } catch (ClassCastException e) {
1369: log.error("Parameter (" + name
1370: + ") could not be converted to a StringKey", e);
1371: }
1372: return result;
1373: }
1374:
1375: /**
1376: * Uses bean introspection to set writable properties of bean from
1377: * the parameters, where a (case-insensitive) name match between
1378: * the bean property and the parameter is looked for.
1379: *
1380: * @param bean An Object.
1381: * @exception Exception a generic exception.
1382: */
1383: public void setProperties(Object bean) throws Exception {
1384: Class beanClass = bean.getClass();
1385: PropertyDescriptor[] props = Introspector
1386: .getBeanInfo(beanClass).getPropertyDescriptors();
1387:
1388: for (int i = 0; i < props.length; i++) {
1389: String propname = props[i].getName();
1390: Method setter = props[i].getWriteMethod();
1391: if (setter != null
1392: && (containsKey(propname)
1393: || containsDateSelectorKeys(propname) || containsTimeSelectorKeys(propname))) {
1394: setProperty(bean, props[i]);
1395: }
1396: }
1397: }
1398:
1399: /**
1400: * Simple method that attempts to get a textual representation of
1401: * this object's name/value pairs. String[] handling is currently
1402: * a bit rough.
1403: *
1404: * @return A textual representation of the parsed name/value pairs.
1405: */
1406: public String toString() {
1407: StringBuffer sb = new StringBuffer();
1408: for (Iterator iter = keySet().iterator(); iter.hasNext();) {
1409: String name = (String) iter.next();
1410:
1411: sb.append('{');
1412: sb.append(name);
1413: sb.append('=');
1414: Object[] params = getToStringParam(name);
1415:
1416: if (params == null) {
1417: sb.append("unknown?");
1418: } else if (params.length == 0) {
1419: sb.append("empty");
1420: } else {
1421: sb.append('[');
1422: for (Iterator it = new ArrayIterator(params); it
1423: .hasNext();) {
1424: sb.append(it.next());
1425: if (it.hasNext()) {
1426: sb.append(", ");
1427: }
1428: }
1429: sb.append(']');
1430: }
1431: sb.append("}\n");
1432: }
1433:
1434: return sb.toString();
1435: }
1436:
1437: /**
1438: * This method is only used in toString() and can be used by
1439: * derived classes to add their local parameters to the toString()
1440:
1441: * @param name A string with the name
1442: *
1443: * @return the value object array or null if not set
1444: */
1445: protected Object[] getToStringParam(final String name) {
1446: return getParam(name);
1447: }
1448:
1449: /**
1450: * Set the property 'prop' in the bean to the value of the
1451: * corresponding parameters. Supports all types supported by
1452: * getXXX methods plus a few more that come for free because
1453: * primitives have to be wrapped before being passed to invoke
1454: * anyway.
1455: *
1456: * @param bean An Object.
1457: * @param prop A PropertyDescriptor.
1458: * @exception Exception a generic exception.
1459: */
1460: protected void setProperty(Object bean, PropertyDescriptor prop)
1461: throws Exception {
1462: if (prop instanceof IndexedPropertyDescriptor) {
1463: throw new Exception(prop.getName()
1464: + " is an indexed property (not supported)");
1465: }
1466:
1467: Method setter = prop.getWriteMethod();
1468: if (setter == null) {
1469: throw new Exception(prop.getName()
1470: + " is a read only property");
1471: }
1472:
1473: Class propclass = prop.getPropertyType();
1474: Object[] args = { null };
1475:
1476: if (propclass == String.class) {
1477: args[0] = getString(prop.getName());
1478: } else if (propclass == Integer.class
1479: || propclass == Integer.TYPE) {
1480: args[0] = getIntObject(prop.getName());
1481: } else if (propclass == Long.class || propclass == Long.TYPE) {
1482: args[0] = new Long(getLong(prop.getName()));
1483: } else if (propclass == Boolean.class
1484: || propclass == Boolean.TYPE) {
1485: args[0] = getBooleanObject(prop.getName());
1486: } else if (propclass == Double.class
1487: || propclass == Double.TYPE) {
1488: args[0] = new Double(getDouble(prop.getName()));
1489: } else if (propclass == BigDecimal.class) {
1490: args[0] = getBigDecimal(prop.getName());
1491: } else if (propclass == String[].class) {
1492: args[0] = getStrings(prop.getName());
1493: } else if (propclass == Object.class) {
1494: args[0] = getObject(prop.getName());
1495: } else if (propclass == int[].class) {
1496: args[0] = getInts(prop.getName());
1497: } else if (propclass == Integer[].class) {
1498: args[0] = getIntObjects(prop.getName());
1499: } else if (propclass == Date.class) {
1500: args[0] = getDate(prop.getName());
1501: } else if (propclass == NumberKey.class) {
1502: args[0] = getNumberKey(prop.getName());
1503: } else if (propclass == StringKey.class) {
1504: args[0] = getStringKey(prop.getName());
1505: } else {
1506: throw new Exception("property " + prop.getName()
1507: + " is of unsupported type " + propclass.toString());
1508: }
1509:
1510: setter.invoke(bean, args);
1511: }
1512:
1513: /**
1514: * Writes a log message about a convertion failure.
1515: *
1516: * @param paramName name of the parameter which could not be converted
1517: * @param value value of the parameter
1518: * @param type target data type.
1519: */
1520: private void logConvertionFailure(String paramName, String value,
1521: String type) {
1522: if (log.isWarnEnabled()) {
1523: log.warn("Parameter (" + paramName + ") with value of ("
1524: + value + ") could not be converted to a " + type);
1525: }
1526: }
1527:
1528: /**
1529: * Puts a key into the parameters map. Makes sure that the name is always
1530: * mapped correctly. This method also enforces the usage of arrays for the
1531: * parameters.
1532: *
1533: * @param name A String with the name.
1534: * @param value An array of Objects with the values.
1535: *
1536: */
1537: protected void putParam(final String name, final String[] value) {
1538: String key = convert(name);
1539: if (key != null) {
1540: parameters.put(key, value);
1541: }
1542: }
1543:
1544: /**
1545: * fetches a key from the parameters map. Makes sure that the name is
1546: * always mapped correctly.
1547: *
1548: * @param name A string with the name
1549: *
1550: * @return the value object array or null if not set
1551: */
1552: protected String[] getParam(final String name) {
1553: String key = convert(name);
1554:
1555: return (key != null) ? (String[]) parameters.get(key) : null;
1556: }
1557: }
|