| package org.apache.fulcrum.parser; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.beans.IndexedPropertyDescriptor; |
| import java.beans.Introspector; |
| import java.beans.PropertyDescriptor; |
| import java.io.UnsupportedEncodingException; |
| import java.lang.reflect.Method; |
| import java.math.BigDecimal; |
| import java.text.DateFormat; |
| import java.text.NumberFormat; |
| import java.text.ParseException; |
| import java.text.ParsePosition; |
| import java.util.Date; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.Locale; |
| import java.util.Set; |
| |
| import org.apache.avalon.framework.logger.LogEnabled; |
| import org.apache.avalon.framework.logger.Logger; |
| import org.apache.commons.lang3.ArrayUtils; |
| import org.apache.commons.lang3.StringUtils; |
| |
| /** |
| * BaseValueParser is a base class for classes that need to parse |
| * name/value Parameters, for example GET/POST data or Cookies |
| * (DefaultParameterParser and DefaultCookieParser) |
| * |
| * <p>It can also be used standalone, for an example see DataStreamParser. |
| * |
| * <p>NOTE: The name= portion of a name=value pair may be converted |
| * to lowercase or uppercase when the object is initialized and when |
| * new data is added. This behavior is determined by the url.case.folding |
| * property in TurbineResources.properties. Adding a name/value pair may |
| * overwrite existing name=value pairs if the names match: |
| * |
| * <pre> |
| * ValueParser vp = new BaseValueParser(); |
| * vp.add("ERROR",1); |
| * vp.add("eRrOr",2); |
| * int result = vp.getInt("ERROR"); |
| * </pre> |
| * |
| * In the above example, result is 2. |
| * |
| * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a> |
| * @author <a href="mailto:jon@clearink.com">Jon S. Stevens</a> |
| * @author <a href="mailto:sean@informage.net">Sean Legassick</a> |
| * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a> |
| * @author <a href="mailto:jh@byteaction.de">Jürgen Hoffmann</a> |
| * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a> |
| * @version $Id$ |
| */ |
| public class BaseValueParser |
| implements ValueParser, |
| ParserServiceSupport, LogEnabled |
| { |
| /** The ParserService instance to query for conversion and configuration */ |
| protected ParserService parserService; |
| |
| /** A convenience logger */ |
| private Logger logger; |
| |
| /** String values which would evaluate to Boolean.TRUE */ |
| private static final String[] TRUE_VALUES = {"TRUE","T","YES","Y","1","ON"}; |
| |
| /** String values which would evaluate to Boolean.FALSE */ |
| private static final String[] FALSE_VALUES = {"FALSE","F","NO","N","0","OFF"}; |
| |
| /** |
| * The character encoding to use when converting to byte arrays |
| */ |
| private String characterEncoding = DEFAULT_CHARACTER_ENCODING; |
| |
| /** |
| * Random access storage for parameter data. |
| */ |
| protected Hashtable<String, Object> parameters = new Hashtable<String, Object>(); |
| |
| /** The locale to use when converting dates, floats and decimals */ |
| private Locale locale = Locale.getDefault(); |
| |
| /** The DateFormat to use for converting dates */ |
| private DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, locale); |
| |
| /** The NumberFormat to use when converting floats and decimals */ |
| private NumberFormat numberFormat = NumberFormat.getNumberInstance(locale); |
| |
| public BaseValueParser() |
| { |
| this(DEFAULT_CHARACTER_ENCODING); |
| } |
| |
| /** |
| * Constructor that takes a character encoding |
| * |
| * @param characterEncoding desired character encoding |
| */ |
| public BaseValueParser(String characterEncoding) |
| { |
| this(characterEncoding, Locale.getDefault()); |
| } |
| |
| /** |
| * Constructor that takes a character encoding and a locale |
| * |
| * @param characterEncoding Sets the character encoding |
| * @param locale Sets the locale |
| */ |
| public BaseValueParser(String characterEncoding, Locale locale) |
| { |
| super(); |
| recycle(characterEncoding); |
| setLocale(locale); |
| } |
| |
| /** |
| * Set a ParserService instance |
| * |
| * @param parserService The parser service instance |
| */ |
| @Override |
| public void setParserService(ParserService parserService) |
| { |
| this.parserService = parserService; |
| } |
| |
| /** |
| * @see org.apache.avalon.framework.logger.LogEnabled#enableLogging(org.apache.avalon.framework.logger.Logger) |
| * @param logger The logger to be used |
| */ |
| @Override |
| public void enableLogging(Logger logger) |
| { |
| this.logger = logger; |
| } |
| |
| /** |
| * Provide an Avalon logger to the derived classes |
| * |
| * @return An Avalon logger instance |
| */ |
| protected Logger getLogger() |
| { |
| return logger; |
| } |
| |
| /** |
| * Recycles the parser. |
| */ |
| public final void recycle() |
| { |
| recycle(DEFAULT_CHARACTER_ENCODING); |
| } |
| |
| /** |
| * Recycles the parser with a character encoding. |
| * |
| * @param characterEncoding the character encoding. |
| */ |
| public final void recycle(String characterEncoding) |
| { |
| setCharacterEncoding(characterEncoding); |
| } |
| |
| /** |
| * Disposes the parser. |
| */ |
| @Override |
| public void dispose() |
| { |
| clear(); |
| disposed = true; |
| } |
| |
| /** |
| * Clear all name/value pairs out of this object. |
| */ |
| @Override |
| public void clear() |
| { |
| parameters.clear(); |
| } |
| |
| /** |
| * Set the character encoding that will be used by this ValueParser. |
| */ |
| @Override |
| public final void setCharacterEncoding(String s) |
| { |
| characterEncoding = s; |
| } |
| |
| /** |
| * Get the character encoding that will be used by this ValueParser. |
| */ |
| @Override |
| public String getCharacterEncoding() |
| { |
| return characterEncoding; |
| } |
| |
| /** |
| * Set the locale that will be used by this ValueParser. |
| */ |
| @Override |
| public final void setLocale(Locale l) |
| { |
| locale = l; |
| setDateFormat(DateFormat.getDateInstance(DateFormat.SHORT, locale)); |
| setNumberFormat(NumberFormat.getNumberInstance(locale)); |
| } |
| |
| /** |
| * Get the locale that will be used by this ValueParser. |
| */ |
| @Override |
| public final Locale getLocale() |
| { |
| return locale; |
| } |
| |
| /** |
| * Set the date format that will be used by this ValueParser. |
| */ |
| @Override |
| public final void setDateFormat(DateFormat df) |
| { |
| dateFormat = df; |
| } |
| |
| /** |
| * Get the date format that will be used by this ValueParser. |
| */ |
| @Override |
| public DateFormat getDateFormat() |
| { |
| return dateFormat; |
| } |
| |
| /** |
| * Set the number format that will be used by this ValueParser. |
| */ |
| @Override |
| public void setNumberFormat(NumberFormat nf) |
| { |
| numberFormat = nf; |
| } |
| |
| /** |
| * Get the number format that will be used by this ValueParser. |
| */ |
| @Override |
| public NumberFormat getNumberFormat() |
| { |
| return numberFormat; |
| } |
| |
| /** |
| * Add a name/value pair into this object. |
| * |
| * @param name A String with the name. |
| * @param value A double with the value. |
| */ |
| @Override |
| public void add(String name, double value) |
| { |
| add(name, numberFormat.format(value)); |
| } |
| |
| /** |
| * Add a name/value pair into this object. |
| * |
| * @param name A String with the name. |
| * @param value An int with the value. |
| */ |
| @Override |
| public void add(String name, int value) |
| { |
| add(name, (long)value); |
| } |
| |
| /** |
| * Add a name/value pair into this object. |
| * |
| * @param name A String with the name. |
| * @param value An Integer with the value. |
| */ |
| @Override |
| public void add(String name, Integer value) |
| { |
| if (value != null) |
| { |
| add(name, value.intValue()); |
| } |
| } |
| |
| /** |
| * Add a name/value pair into this object. |
| * |
| * @param name A String with the name. |
| * @param value A long with the value. |
| */ |
| @Override |
| public void add(String name, long value) |
| { |
| add(name, Long.toString(value)); |
| } |
| |
| /** |
| * Add a name/value pair into this object. |
| * |
| * @param name A String with the name. |
| * @param value A long with the value. |
| */ |
| @Override |
| public void add(String name, String value) |
| { |
| if (value != null) |
| { |
| String [] items = getParam(name); |
| items = ArrayUtils.add(items, value); |
| putParam(name, items); |
| } |
| } |
| |
| /** |
| * Add an array of Strings for a key. This |
| * is simply adding all the elements in the |
| * array one by one. |
| * |
| * @param name A String with the name. |
| * @param value A String Array. |
| */ |
| @Override |
| public void add(String name, String [] value) |
| { |
| // ArrayUtils.addAll() looks promising but it would also add |
| // null values into the parameters array, so we can't use that. |
| if (value != null) |
| { |
| for (int i = 0 ; i < value.length; i++) |
| { |
| if (value[i] != null) |
| { |
| add(name, value[i]); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Removes the named parameter from the contained hashtable. Wraps to the |
| * contained <code>Map.remove()</code>. |
| * |
| * @return The value that was mapped to the key (a <code>String[]</code>) |
| * or <code>null</code> if the key was not mapped. |
| */ |
| @Override |
| public Object remove(String name) |
| { |
| return parameters.remove(convert(name)); |
| } |
| |
| /** |
| * Trims the string data and applies the conversion specified in |
| * the property given by URL_CASE_FOLDING. It returns a new |
| * string so that it does not destroy the value data. |
| * |
| * @param value A String to be processed. |
| * @return A new String converted to lowercase and trimmed. |
| */ |
| @Override |
| public String convert(String value) |
| { |
| return convertAndTrim(value); |
| } |
| |
| /** |
| * Determine whether a given key has been inserted. All keys are |
| * stored in lowercase strings, so override method to account for |
| * this. |
| * |
| * @param key An Object with the key to search for. |
| * @return True if the object is found. |
| */ |
| @Override |
| public boolean containsKey(Object key) |
| { |
| return parameters.containsKey(convert(String.valueOf(key))); |
| } |
| |
| /** |
| * Gets the set of keys |
| * |
| * @return A <code>Set</code> of the keys. |
| */ |
| @Override |
| public Set<String> keySet() |
| { |
| return parameters.keySet(); |
| } |
| |
| /** |
| * Returns all the available parameter names. |
| * |
| * @return A object array with the keys. |
| */ |
| @Override |
| public String[] getKeys() |
| { |
| return keySet().toArray(new String[0]); |
| } |
| |
| /** |
| * Gets an iterator over the set of keys |
| * |
| * @return An <code>Iterator</code> over the keys. |
| */ |
| @Override |
| public Iterator<String> iterator() |
| { |
| return parameters.keySet().iterator(); |
| } |
| |
| /** |
| * Returns a Boolean object for the given string. If the value |
| * can not be parsed as a boolean, null is returned. |
| * <p> |
| * Valid values for true: true, t, on, 1, yes, y<br> |
| * Valid values for false: false, f, off, 0, no, n<br> |
| * <p> |
| * The string is compared without reguard to case. |
| * |
| * @param string A String with the value. |
| * @return A Boolean. |
| */ |
| private Boolean parseBoolean(String string) |
| { |
| Boolean result = null; |
| String value = StringUtils.trim(string); |
| |
| if (StringUtils.isNotEmpty(value)) |
| { |
| for (int cnt = 0; |
| cnt < Math.max(TRUE_VALUES.length, FALSE_VALUES.length); cnt++) |
| { |
| // Short-cut evaluation or bust! |
| if (cnt < TRUE_VALUES.length && |
| value.equalsIgnoreCase(TRUE_VALUES[cnt])) |
| { |
| result = Boolean.TRUE; |
| break; |
| } |
| |
| if (cnt < FALSE_VALUES.length && |
| value.equalsIgnoreCase(FALSE_VALUES[cnt])) |
| { |
| result = Boolean.FALSE; |
| break; |
| } |
| } |
| |
| if (result == null && getLogger().isWarnEnabled() == true) |
| { |
| getLogger().warn("Parameter with value of (" |
| + value + ") could not be converted to a Boolean"); |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Return a boolean for the given name. If the name does not |
| * exist, return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A boolean. |
| */ |
| @Override |
| public boolean getBoolean(String name, boolean defaultValue) |
| { |
| Boolean result = getBooleanObject(name); |
| return (result == null ? defaultValue : result.booleanValue()); |
| } |
| |
| /** |
| * Return a boolean for the given name. If the name does not |
| * exist, return false. |
| * |
| * @param name A String with the name. |
| * @return A boolean. |
| */ |
| @Override |
| public boolean getBoolean(String name) |
| { |
| return getBoolean(name, false); |
| } |
| |
| /** |
| * Return an array of booleans for the given name. If the name does |
| * not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A boolean[]. |
| */ |
| @Override |
| public boolean[] getBooleans(String name) |
| { |
| boolean[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new boolean[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| // default to false |
| result[i] = false; |
| |
| // update with parsed value if exists |
| Boolean bool = parseBoolean(value[i]); |
| if ( bool != null ) |
| { |
| result[i] = bool.booleanValue(); |
| } |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a Boolean object for the given name. If the parameter |
| * does not exist or can not be parsed as a boolean, null is returned. |
| * <p> |
| * Valid values for true: true, on, 1, yes<br> |
| * Valid values for false: false, off, 0, no<br> |
| * <p> |
| * The string is compared without reguard to case. |
| * |
| * @param name A String with the name. |
| * @return A Boolean. |
| */ |
| @Override |
| public Boolean getBooleanObject(String name) |
| { |
| return parseBoolean(getString(name)); |
| } |
| |
| /** |
| * Returns a Boolean object for the given name. If the parameter |
| * does not exist or can not be parsed as a boolean, null is returned. |
| * <p> |
| * Valid values for true: true, on, 1, yes<br> |
| * Valid values for false: false, off, 0, no<br> |
| * <p> |
| * The string is compared without reguard to case. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A Boolean. |
| */ |
| @Override |
| public Boolean getBooleanObject(String name, Boolean defaultValue) |
| { |
| Boolean result = getBooleanObject(name); |
| return (result == null ? defaultValue : result); |
| } |
| |
| /** |
| * Return an array of Booleans for the given name. If the name does |
| * not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A Boolean[]. |
| */ |
| @Override |
| public Boolean[] getBooleanObjects(String name) |
| { |
| Boolean[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new Boolean[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| result[i] = parseBoolean(value[i]); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return a {@link Number} for the given string. |
| * |
| * @param string A String with the value. |
| * @return A Number. |
| * |
| */ |
| private Number parseNumber(String string) |
| { |
| Number result = null; |
| String value = StringUtils.trim(string); |
| |
| if (StringUtils.isNotEmpty(value)) |
| { |
| ParsePosition pos = new ParsePosition(0); |
| Number number = numberFormat.parse(value, pos); |
| |
| if (pos.getIndex() == value.length()) |
| { |
| // completely parsed |
| result = number; |
| } |
| else |
| { |
| if (getLogger().isWarnEnabled()) |
| { |
| getLogger().warn("Parameter with value of (" |
| + value + ") could not be converted to a Number at position " + pos.getIndex()); |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Return a {@link Number} for the given name. If the name does not |
| * exist, return null. This is the base function for all numbers. |
| * |
| * @param name A String with the name. |
| * @return A Number. |
| * |
| */ |
| private Number getNumber(String name) |
| { |
| return parseNumber(getString(name)); |
| } |
| |
| /** |
| * Return a double for the given name. If the name does not |
| * exist, return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A double. |
| */ |
| @Override |
| public double getDouble(String name, double defaultValue) |
| { |
| Number number = getNumber(name); |
| return (number == null ? defaultValue : number.doubleValue()); |
| } |
| |
| /** |
| * Return a double for the given name. If the name does not |
| * exist, return 0.0. |
| * |
| * @param name A String with the name. |
| * @return A double. |
| */ |
| @Override |
| public double getDouble(String name) |
| { |
| return getDouble(name, 0.0); |
| } |
| |
| /** |
| * Return an array of doubles for the given name. If the name does |
| * not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A double[]. |
| */ |
| @Override |
| public double[] getDoubles(String name) |
| { |
| double[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new double[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| Number number = parseNumber(value[i]); |
| result[i] = (number == null ? 0.0 : number.doubleValue()); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return a Double for the given name. If the name does not |
| * exist, return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A double. |
| */ |
| @Override |
| public Double getDoubleObject(String name, Double defaultValue) |
| { |
| Number result = getNumber(name); |
| return (result == null ? defaultValue : new Double(result.doubleValue())); |
| } |
| |
| /** |
| * Return a Double for the given name. If the name does not |
| * exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A double. |
| */ |
| @Override |
| public Double getDoubleObject(String name) |
| { |
| return getDoubleObject(name, null); |
| } |
| |
| /** |
| * Return an array of doubles for the given name. If the name does |
| * not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A double[]. |
| */ |
| @Override |
| public Double[] getDoubleObjects(String name) |
| { |
| Double[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new Double[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| Number number = parseNumber(value[i]); |
| result[i] = (number == null ? null : new Double(number.doubleValue())); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return a float for the given name. If the name does not |
| * exist, return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A float. |
| */ |
| @Override |
| public float getFloat(String name, float defaultValue) |
| { |
| Number number = getNumber(name); |
| return (number == null ? defaultValue : number.floatValue()); |
| } |
| |
| /** |
| * Return a float for the given name. If the name does not |
| * exist, return 0.0. |
| * |
| * @param name A String with the name. |
| * @return A float. |
| */ |
| @Override |
| public float getFloat(String name) |
| { |
| return getFloat(name, 0.0f); |
| } |
| |
| /** |
| * Return an array of floats for the given name. If the name does |
| * not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A float[]. |
| */ |
| @Override |
| public float[] getFloats(String name) |
| { |
| float[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new float[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| Number number = parseNumber(value[i]); |
| result[i] = (number == null ? 0.0f : number.floatValue()); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return a Float for the given name. If the name does not |
| * exist, return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A Float. |
| */ |
| @Override |
| public Float getFloatObject(String name, Float defaultValue) |
| { |
| Number result = getNumber(name); |
| return (result == null ? defaultValue : new Float(result.floatValue())); |
| } |
| |
| /** |
| * Return a float for the given name. If the name does not |
| * exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A Float. |
| */ |
| @Override |
| public Float getFloatObject(String name) |
| { |
| return getFloatObject(name, null); |
| } |
| |
| /** |
| * Return an array of floats for the given name. If the name does |
| * not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A float[]. |
| */ |
| @Override |
| public Float[] getFloatObjects(String name) |
| { |
| Float[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new Float[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| Number number = parseNumber(value[i]); |
| result[i] = (number == null ? null : new Float(number.floatValue())); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return a BigDecimal for the given name. If the name does not |
| * exist, return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A BigDecimal. |
| */ |
| @Override |
| public BigDecimal getBigDecimal(String name, BigDecimal defaultValue) |
| { |
| Number result = getNumber(name); |
| return (result == null ? defaultValue : new BigDecimal(result.doubleValue())); |
| } |
| |
| /** |
| * Return a BigDecimal for the given name. If the name does not |
| * exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A BigDecimal. |
| */ |
| @Override |
| public BigDecimal getBigDecimal(String name) |
| { |
| return getBigDecimal(name, null); |
| } |
| |
| /** |
| * Return an array of BigDecimals for the given name. If the name |
| * does not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A BigDecimal[]. |
| */ |
| @Override |
| public BigDecimal[] getBigDecimals(String name) |
| { |
| BigDecimal[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new BigDecimal[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| Number number = parseNumber(value[i]); |
| result[i] = (number == null ? null : new BigDecimal(number.doubleValue())); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return an int for the given name. If the name does not exist, |
| * return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return An int. |
| */ |
| @Override |
| public int getInt(String name, int defaultValue) |
| { |
| Number result = getNumber(name); |
| return (result == null || result instanceof Double ? defaultValue : result.intValue()); |
| } |
| |
| /** |
| * Return an int for the given name. If the name does not exist, |
| * return 0. |
| * |
| * @param name A String with the name. |
| * @return An int. |
| */ |
| @Override |
| public int getInt(String name) |
| { |
| return getInt(name, 0); |
| } |
| |
| /** |
| * Return an array of ints for the given name. If the name does |
| * not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return An int[]. |
| */ |
| @Override |
| public int[] getInts(String name) |
| { |
| int[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new int[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| Number number = parseNumber(value[i]); |
| result[i] = (number == null || number instanceof Double ? 0 : number.intValue()); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return an Integer for the given name. If the name does not exist, |
| * return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return An Integer. |
| */ |
| @Override |
| public Integer getIntObject(String name, Integer defaultValue) |
| { |
| Number result = getNumber(name); |
| return (result == null || result instanceof Double ? defaultValue : Integer.valueOf(result.intValue())); |
| } |
| |
| /** |
| * Return an Integer for the given name. If the name does not exist, |
| * return null. |
| * |
| * @param name A String with the name. |
| * @return An Integer. |
| */ |
| @Override |
| public Integer getIntObject(String name) |
| { |
| return getIntObject(name, null); |
| } |
| |
| /** |
| * Return an array of Integers for the given name. If the name |
| * does not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return An Integer[]. |
| */ |
| @Override |
| public Integer[] getIntObjects(String name) |
| { |
| Integer[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new Integer[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| Number number = parseNumber(value[i]); |
| result[i] = (number == null || number instanceof Double ? null : Integer.valueOf(number.intValue())); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return a long for the given name. If the name does not exist, |
| * return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A long. |
| */ |
| @Override |
| public long getLong(String name, long defaultValue) |
| { |
| Number result = getNumber(name); |
| return (result == null || result instanceof Double ? defaultValue : result.longValue()); |
| } |
| |
| /** |
| * Return a long for the given name. If the name does not exist, |
| * return 0. |
| * |
| * @param name A String with the name. |
| * @return A long. |
| */ |
| @Override |
| public long getLong(String name) |
| { |
| return getLong(name, 0); |
| } |
| |
| /** |
| * Return an array of longs for the given name. If the name does |
| * not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A long[]. |
| */ |
| @Override |
| public long[] getLongs(String name) |
| { |
| long[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new long[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| Number number = parseNumber(value[i]); |
| result[i] = (number == null || number instanceof Double ? 0L : number.longValue()); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return an array of Longs for the given name. If the name does |
| * not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A Long[]. |
| */ |
| @Override |
| public Long[] getLongObjects(String name) |
| { |
| Long[] result = null; |
| String value[] = getParam(name); |
| if (value != null) |
| { |
| result = new Long[value.length]; |
| for (int i = 0; i < value.length; i++) |
| { |
| Number number = parseNumber(value[i]); |
| result[i] = (number == null || number instanceof Double ? null : Long.valueOf(number.longValue())); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return a Long for the given name. If the name does |
| * not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A Long. |
| */ |
| @Override |
| public Long getLongObject(String name) |
| { |
| return getLongObject(name, null); |
| } |
| |
| /** |
| * Return a Long for the given name. If the name does |
| * not exist, return the default value. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A Long. |
| */ |
| @Override |
| public Long getLongObject(String name, Long defaultValue) |
| { |
| Number result = getNumber(name); |
| return (result == null || result instanceof Double ? defaultValue : Long.valueOf(result.longValue())); |
| } |
| |
| /** |
| * Return a byte for the given name. If the name does not exist, |
| * return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A byte. |
| */ |
| @Override |
| public byte getByte(String name, byte defaultValue) |
| { |
| Number result = getNumber(name); |
| return (result == null || result instanceof Double ? defaultValue : result.byteValue()); |
| } |
| |
| /** |
| * Return a byte for the given name. If the name does not exist, |
| * return 0. |
| * |
| * @param name A String with the name. |
| * @return A byte. |
| */ |
| @Override |
| public byte getByte(String name) |
| { |
| return getByte(name, (byte) 0); |
| } |
| |
| /** |
| * Return an array of bytes for the given name. If the name does |
| * not exist, return null. The array is returned according to the |
| * HttpRequest's character encoding. |
| * |
| * @param name A String with the name. |
| * @return A byte[]. |
| * @throws UnsupportedEncodingException Generic exception |
| */ |
| @Override |
| public byte[] getBytes(String name) |
| throws UnsupportedEncodingException |
| { |
| byte result[] = null; |
| String value = getString(name); |
| if (value != null) |
| { |
| result = value.getBytes(getCharacterEncoding()); |
| } |
| return result; |
| } |
| |
| /** |
| * Return a byte for the given name. If the name does not exist, |
| * return defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A byte. |
| */ |
| @Override |
| public Byte getByteObject(String name, Byte defaultValue) |
| { |
| Number result = getNumber(name); |
| return (result == null || result instanceof Double ? defaultValue : Byte.valueOf(result.byteValue())); |
| } |
| |
| /** |
| * Return a byte for the given name. If the name does not exist, |
| * return 0. |
| * |
| * @param name A String with the name. |
| * @return A byte. |
| */ |
| @Override |
| public Byte getByteObject(String name) |
| { |
| return getByteObject(name, null); |
| } |
| |
| /** |
| * Return a String for the given name. If the name does not |
| * exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A String or null if the key is unknown. |
| */ |
| @Override |
| public String getString(String name) |
| { |
| String [] value = getParam(name); |
| return value == null || value.length == 0 ? null : value[0]; |
| } |
| |
| /** |
| * Return a String for the given name. If the name does not |
| * exist, return null. It is the same as the getString() method |
| * however has been added for simplicity when working with |
| * template tools such as Velocity which allow you to do |
| * something like this: |
| * |
| * <code>$data.Parameters.form_variable_name</code> |
| * |
| * @param name A String with the name. |
| * @return A String. |
| */ |
| @Override |
| public String get(String name) |
| { |
| return getString(name); |
| } |
| |
| /** |
| * Return a String for the given name. If the name does not |
| * exist, return the defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A String. |
| */ |
| @Override |
| public String getString(String name, String defaultValue) |
| { |
| String value = getString(name); |
| return StringUtils.isEmpty(value) ? defaultValue : value; |
| } |
| |
| /** |
| * Set a parameter to a specific value. |
| * |
| * This is useful if you want your action to override the values |
| * of the parameters for the screen to use. |
| * @param name The name of the parameter. |
| * @param value The value to set. |
| */ |
| @Override |
| public void setString(String name, String value) |
| { |
| if (value != null) |
| { |
| putParam(name, new String[]{value}); |
| } |
| } |
| |
| /** |
| * Return an array of Strings for the given name. If the name |
| * does not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A String[]. |
| */ |
| @Override |
| public String[] getStrings(String name) |
| { |
| return getParam(name); |
| } |
| |
| /** |
| * Return an array of Strings for the given name. If the name |
| * does not exist, return the defaultValue. |
| * |
| * @param name A String with the name. |
| * @param defaultValue The default value. |
| * @return A String[]. |
| */ |
| @Override |
| public String[] getStrings(String name, String[] defaultValue) |
| { |
| String[] value = getParam(name); |
| return value == null || value.length == 0 ? defaultValue : value; |
| } |
| |
| /** |
| * Set a parameter to a specific value. |
| * |
| * This is useful if you want your action to override the values |
| * of the parameters for the screen to use. |
| * @param name The name of the parameter. |
| * @param values The value to set. |
| */ |
| @Override |
| public void setStrings(String name, String[] values) |
| { |
| if (values != null) |
| { |
| putParam(name, values); |
| } |
| } |
| |
| /** |
| * Return an Object for the given name. If the name does not |
| * exist, return null. |
| * |
| * @param name A String with the name. |
| * @return An Object. |
| */ |
| @Override |
| public Object getObject(String name) |
| { |
| return getString(name); |
| } |
| |
| /** |
| * Return an array of Objects for the given name. If the name |
| * does not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return An Object[]. |
| */ |
| @Override |
| public Object[] getObjects(String name) |
| { |
| return getParam(name); |
| } |
| |
| /** |
| * Returns a {@link java.util.Date} object. String is parsed by supplied |
| * DateFormat. If the name does not exist or the value could not be |
| * parsed into a date return the defaultValue. |
| * |
| * @param name A String with the name. |
| * @param df A DateFormat. |
| * @param defaultValue The default value. |
| * @return A Date. |
| */ |
| @Override |
| public Date getDate(String name, DateFormat df, Date defaultValue) |
| { |
| Date result = defaultValue; |
| String value = StringUtils.trim(getString(name)); |
| if (StringUtils.isNotEmpty(value)) |
| { |
| try |
| { |
| // Reject invalid dates. |
| df.setLenient(false); |
| result = df.parse(value); |
| } |
| catch (ParseException e) |
| { |
| logConversionFailure(name, value, "Date"); |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Returns a {@link java.util.Date} object. If there are DateSelector or |
| * TimeSelector style parameters then these are used. If not and there |
| * is a parameter 'name' then this is parsed by DateFormat. If the |
| * name does not exist, return null. |
| * |
| * @param name A String with the name. |
| * @return A Date. |
| */ |
| @Override |
| public Date getDate(String name) |
| { |
| return getDate(name, dateFormat, null); |
| } |
| |
| /** |
| * Returns a {@link java.util.Date} object. String is parsed by supplied |
| * DateFormat. If the name does not exist, return null. |
| * |
| * @param name A String with the name. |
| * @param df A DateFormat. |
| * @return A Date. |
| */ |
| @Override |
| public Date getDate(String name, DateFormat df) |
| { |
| return getDate(name, df, null); |
| } |
| |
| /** |
| * Uses bean introspection to set writable properties of bean from |
| * the parameters, where a (case-insensitive) name match between |
| * the bean property and the parameter is looked for. |
| * |
| * @param bean An Object. |
| * @throws Exception a generic exception. |
| */ |
| @Override |
| public void setProperties(Object bean) throws Exception |
| { |
| Class<?> beanClass = bean.getClass(); |
| PropertyDescriptor[] props |
| = Introspector.getBeanInfo(beanClass).getPropertyDescriptors(); |
| |
| for ( PropertyDescriptor pd : props ) |
| { |
| String propname = pd.getName(); |
| Method setter = pd.getWriteMethod(); |
| if (setter != null && containsKey(propname)) |
| { |
| setProperty(bean, pd); |
| } |
| } |
| } |
| |
| /** |
| * Simple method that attempts to get a textual representation of |
| * this object's name/value pairs. String[] handling is currently |
| * a bit rough. |
| * |
| * @return A textual representation of the parsed name/value pairs. |
| */ |
| @Override |
| public String toString() |
| { |
| StringBuilder sb = new StringBuilder(); |
| for (String name : keySet()) |
| { |
| sb.append('{'); |
| sb.append(name); |
| sb.append('='); |
| Object [] params = getToStringParam(name); |
| |
| if (params == null) |
| { |
| sb.append("unknown?"); |
| } |
| else if (params.length == 0) |
| { |
| sb.append("empty"); |
| } |
| else |
| { |
| sb.append('['); |
| sb.append(StringUtils.join(params, ", ")); |
| sb.append(']'); |
| } |
| sb.append("}\n"); |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * This method is only used in toString() and can be used by |
| * derived classes to add their local parameters to the toString() |
| |
| * @param name A string with the name |
| * |
| * @return the value object array or null if not set |
| */ |
| protected Object [] getToStringParam(final String name) |
| { |
| return getParam(name); |
| } |
| |
| /** |
| * Set the property 'prop' in the bean to the value of the |
| * corresponding parameters. Supports all types supported by |
| * getXXX methods plus a few more that come for free because |
| * primitives have to be wrapped before being passed to invoke |
| * anyway. |
| * |
| * @param bean An Object. |
| * @param prop A PropertyDescriptor. |
| * @@throws Exception a generic exception. |
| */ |
| protected void setProperty(Object bean, |
| PropertyDescriptor prop) |
| throws Exception |
| { |
| if (prop instanceof IndexedPropertyDescriptor) |
| { |
| throw new Exception(prop.getName() + |
| " is an indexed property (not supported)"); |
| } |
| |
| Method setter = prop.getWriteMethod(); |
| if (setter == null) |
| { |
| throw new Exception(prop.getName() + |
| " is a read only property"); |
| } |
| |
| Class<?> propclass = prop.getPropertyType(); |
| Object arg = null; |
| |
| if (propclass == String.class) |
| { |
| arg = getString(prop.getName()); |
| } |
| else if (propclass == Byte.class || propclass == Byte.TYPE) |
| { |
| arg = getByteObject(prop.getName()); |
| } |
| else if (propclass == Integer.class || propclass == Integer.TYPE) |
| { |
| arg = getIntObject(prop.getName()); |
| } |
| else if (propclass == Long.class || propclass == Long.TYPE) |
| { |
| arg = getLongObject(prop.getName()); |
| } |
| else if (propclass == Boolean.class || propclass == Boolean.TYPE) |
| { |
| arg = getBooleanObject(prop.getName()); |
| } |
| else if (propclass == Double.class || propclass == Double.TYPE) |
| { |
| arg = getDoubleObject(prop.getName()); |
| } |
| else if (propclass == Float.class || propclass == Float.TYPE) |
| { |
| arg = getFloatObject(prop.getName()); |
| } |
| else if (propclass == BigDecimal.class) |
| { |
| arg = getBigDecimal(prop.getName()); |
| } |
| else if (propclass == String[].class) |
| { |
| arg = getStrings(prop.getName()); |
| } |
| else if (propclass == Object.class) |
| { |
| arg = getObject(prop.getName()); |
| } |
| else if (propclass == int[].class) |
| { |
| arg = getInts(prop.getName()); |
| } |
| else if (propclass == Integer[].class) |
| { |
| arg = getIntObjects(prop.getName()); |
| } |
| else if (propclass == Date.class) |
| { |
| arg = getDate(prop.getName()); |
| } |
| else |
| { |
| throw new Exception("property " |
| + prop.getName() |
| + " is of unsupported type " |
| + propclass.toString()); |
| } |
| |
| setter.invoke(bean, arg); |
| } |
| |
| /** |
| * Puts a key into the parameters map. Makes sure that the name is always |
| * mapped correctly. This method also enforces the usage of arrays for the |
| * parameters. |
| * |
| * @param name A String with the name. |
| * @param value An array of Objects with the values. |
| * |
| */ |
| protected void putParam(final String name, final String [] value) |
| { |
| String key = convert(name); |
| if (key != null) |
| { |
| parameters.put(key, value); |
| } |
| } |
| |
| /** |
| * fetches a key from the parameters map. Makes sure that the name is |
| * always mapped correctly. |
| * |
| * @param name A string with the name |
| * |
| * @return the value object array or null if not set |
| */ |
| protected String [] getParam(final String name) |
| { |
| String key = convert(name); |
| Object value = parameters.get(key); |
| |
| // todo sgoeschl 20070405 quick fix for Scott's test case - need to |
| // be reworked for proper functioning according to TV |
| if(value instanceof String[]) |
| { |
| return (String []) parameters.get(key); |
| } |
| else |
| { |
| return null; |
| } |
| } |
| |
| |
| /** recyclable support **/ |
| |
| /** |
| * The disposed flag. |
| */ |
| private boolean disposed; |
| |
| /** |
| * Checks whether the object is disposed. |
| * |
| * @return true, if the object is disposed. |
| */ |
| public boolean isDisposed() |
| { |
| return disposed; |
| } |
| |
| /** |
| * Writes a log message about a conversion failure. |
| * |
| * @param paramName name of the parameter which could not be converted |
| * @param value value of the parameter |
| * @param type target data type. |
| */ |
| private void logConversionFailure(String paramName, |
| String value, String type) |
| { |
| getLogger().warn("Parameter (" + paramName |
| + ") with value of (" |
| + value + ") could not be converted to a " + type); |
| } |
| |
| /** |
| * Convert a String value according to the url-case-folding property. |
| * |
| * @param value the String to convert |
| * |
| * @return a new String. |
| * |
| */ |
| @Override |
| public String convertAndTrim(String value) |
| { |
| return parserService.convertAndTrim(value); |
| } |
| |
| /** |
| * A convert method, which trims the string data and applies the |
| * conversion specified in the parameter given. It returns a new |
| * string so that it does not destroy the value data. |
| * |
| * @param value A String to be processed. |
| * @param fold The parameter folding to be applied |
| * (see {@link ParserService}) |
| * @return A new String converted to the correct case and trimmed. |
| */ |
| @Override |
| public String convertAndTrim(String value, URLCaseFolding fold) |
| { |
| return parserService.convertAndTrim(value, fold); |
| } |
| |
| /** |
| * Gets the folding value from the ParserService configuration |
| * |
| * @return The current Folding Value |
| */ |
| @Override |
| public URLCaseFolding getUrlFolding() |
| { |
| return parserService.getUrlFolding(); |
| } |
| |
| public boolean isValid() |
| { |
| if ( this.parameters.size() == 0 ) |
| { |
| return true; |
| } |
| return false; |
| } |
| } |