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