craigmcc    01/04/14 11:29:57

  Added:       beanutils/src/java/org/apache/commons/beanutils
                        BeanUtils.java ConvertUtils.java PropertyUtils.java
                        package.html
  Removed:     beanutils/src/share/org/apache/commons/beanutils
                        BeanUtils.java ConvertUtils.java PropertyUtils.java
                        package.html
  Log:
  Migrate "src/share" to "src/java" for consistency.
  
  Revision  Changes    Path
  1.1                  
jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/BeanUtils.java
  
  Index: BeanUtils.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/BeanUtils.java,v
 1.1 2001/04/14 18:29:56 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2001/04/14 18:29:56 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  
  package org.apache.commons.beanutils;
  
  
  import java.beans.BeanInfo;
  import java.beans.IndexedPropertyDescriptor;
  import java.beans.IntrospectionException;
  import java.beans.Introspector;
  import java.beans.PropertyDescriptor;
  import java.lang.reflect.Array;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Iterator;
  import java.util.Map;
  
  
  /**
   * Utility methods for populating JavaBeans properties via reflection.
   *
   * @author Craig R. McClanahan
   * @author Ralph Schaer
   * @author Chris Audley
   * @version $Revision: 1.1 $ $Date: 2001/04/14 18:29:56 $
   */
  
  public class BeanUtils {
  
  
      // ------------------------------------------------------ Private Variables
  
  
      /**
       * The debugging detail level for this component.
       */
      private static int debug = 0;
  
      public static int getDebug() {
          return (debug);
      }
  
      public static void setDebug(int newDebug) {
          debug = newDebug;
      }
  
  
      // --------------------------------------------------------- Public Classes
  
  
      /**
       * Clone a bean based on the available property getters and setters,
       * even if the bean class itself does not implement Cloneable.
       *
       * @param bean Bean to be cloned
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InstantiationException if a new instance of the bean's
       *  class cannot be instantiated
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static Object cloneBean(Object bean)
          throws IllegalAccessException, InstantiationException,
                 InvocationTargetException, NoSuchMethodException {
  
          Class clazz = bean.getClass();
          Object newBean = clazz.newInstance();
          PropertyUtils.copyProperties(newBean, bean);
          return (newBean);
  
      }
  
  
      /**
       * Return the value of the specified array property of the specified
       * bean, as a String array.
       *
       * @param bean Bean whose property is to be extracted
       * @param name Name of the property to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static String[] getArrayProperty(Object bean, String name)
          throws IllegalAccessException, InvocationTargetException,
                 NoSuchMethodException {
  
          Object value = PropertyUtils.getProperty(bean, name);
          if (value == null) {
              return (null);
          } else if (value instanceof Collection) {
              ArrayList values = new ArrayList();
              Iterator items = ((Collection) value).iterator();
              while (items.hasNext()) {
                  Object item = items.next();
                  if (item == null)
                      values.add((String) null);
                  else
                      values.add(item.toString());
              }
              return ((String[]) values.toArray(new String[values.size()]));
          } else if (value.getClass().isArray()) {
              ArrayList values = new ArrayList();
              try {
                  int n = Array.getLength(value);
                  for (int i = 0; i < n; i++) {
                      values.add(Array.get(value, i).toString());
                  }
              } catch (ArrayIndexOutOfBoundsException e) {
                  ;
              }
              return ((String[]) values.toArray(new String[values.size()]));
          } else {
              String results[] = new String[1];
              results[0] = value.toString();
              return (results);
          }
  
      }
  
  
      /**
       * Return the value of the specified indexed property of the specified
       * bean, as a String.  The zero-relative index of the
       * required value must be included (in square brackets) as a suffix to
       * the property name, or <code>IllegalArgumentException</code> will be
       * thrown.
       *
       * @param bean Bean whose property is to be extracted
       * @param name <code>propertyname[index]</code> of the property value
       *  to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static String getIndexedProperty(Object bean, String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
          Object value = PropertyUtils.getIndexedProperty(bean, name);
          return (ConvertUtils.convert(value));
  
      }
  
  
      /**
       * Return the value of the specified indexed property of the specified
       * bean, as a String.  The index is specified as a method parameter and
       * must *not* be included in the property name expression
       *
       * @param bean Bean whose property is to be extracted
       * @param name Simple property name of the property value to be extracted
       * @param index Index of the property value to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static String getIndexedProperty(Object bean,
                                            String name, int index)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
          StringBuffer sb = new StringBuffer(name);
          sb.append(PropertyUtils.INDEXED_DELIM);
          sb.append(index);
          sb.append(PropertyUtils.INDEXED_DELIM2);
          Object value = PropertyUtils.getIndexedProperty(bean, name);
          return (ConvertUtils.convert(value));
  
      }
  
  
      /**
       * Return the value of the (possibly nested) property of the specified
       * name, for the specified bean, as a String.
       *
       * @param bean Bean whose property is to be extracted
       * @param name Possibly nested name of the property to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception IllegalArgumentException if a nested reference to a
       *  property returns null
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static String getNestedProperty(Object bean, String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
          Object value = PropertyUtils.getNestedProperty(bean, name);
          return (ConvertUtils.convert(value));
  
      }
  
  
      /**
       * Return the value of the specified property of the specified bean,
       * no matter which property reference format is used, as a String.
       *
       * @param bean Bean whose property is to be extracted
       * @param name Possibly indexed and/or nested name of the property
       *  to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static String getProperty(Object bean, String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
          return (getNestedProperty(bean, name));
  
      }
  
  
      /**
       * Return the value of the specified simple property of the specified
       * bean, converted to a String.
       *
       * @param bean Bean whose property is to be extracted
       * @param name Name of the property to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static String getSimpleProperty(Object bean, String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
          Object value = PropertyUtils.getSimpleProperty(bean, name);
          return (ConvertUtils.convert(value));
  
      }
  
  
      /**
       * Populate the JavaBeans properties of the specified bean, based on
       * the specified name/value pairs.  This method uses Java reflection APIs
       * to identify corresponding "property setter" method names, and deals
       * with setter arguments of type <code>String</code>, <code>boolean</code>,
       * <code>int</code>, <code>long</code>, <code>float</code>, and
       * <code>double</code>.  In addition, array setters for these types (or the
       * corresponding primitive types) can also be identified.
       * <p>
       * The particular setter method to be called for each property is
       * determined using the usual JavaBeans introspection mechanisms.  Thus,
       * you may identify custom setter methods using a BeanInfo class that is
       * associated with the class of the bean itself.  If no such BeanInfo
       * class is available, the standard method name conversion ("set" plus
       * the capitalized name of the property in question) is used.
       * <p>
       * <strong>NOTE</strong>:  It is contrary to the JavaBeans Specification
       * to have more than one setter method (with different argument
       * signatures) for the same property.
       *
       * @param bean JavaBean whose properties are being populated
       * @param properties Map keyed by property name, with the
       *  corresponding (String or String[]) value(s) to be set
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       */
      public static void populate(Object bean, Map properties)
          throws IllegalAccessException, InvocationTargetException {
  
          if ((bean == null) || (properties == null))
              return;
  
          /*
          if (debug >= 1)
              System.out.println("BeanUtils.populate(" + bean + ", " +
                                 properties + ")");
          */
  
          // Loop through the property name/value pairs to be set
          Iterator names = properties.keySet().iterator();
          while (names.hasNext()) {
  
              // Identify the property name and value(s) to be assigned
              String name = (String) names.next();
              if (name == null)
                  continue;
              Object value = properties.get(name);      // String or String[]
  
              /*
              if (debug >= 1)
                  System.out.println("  name='" + name + "', value.class='" +
                                     (value == null ? "NONE" :
                                     value.getClass().getName()) + "'");
              */
  
              // Get the property descriptor of the requested property (if any)
              PropertyDescriptor descriptor = null;
              try {
                  descriptor = PropertyUtils.getPropertyDescriptor(bean, name);
              } catch (Throwable t) {
                  /*
                  if (debug >= 1)
                      System.out.println("    getPropertyDescriptor: " + t);
                  */
                  descriptor = null;
              }
              if (descriptor == null) {
                  /*
                  if (debug >= 1)
                      System.out.println("    No such property, skipping");
                  */
                  continue;
              }
              /*
              if (debug >= 1)
                  System.out.println("    Property descriptor is '" +
                                     descriptor + "'");
              */
  
              // Identify the relevant setter method (if there is one)
              Method setter = null;
              if (descriptor instanceof IndexedPropertyDescriptor)
                  setter = ((IndexedPropertyDescriptor) descriptor).
                      getIndexedWriteMethod();
              if (setter == null)
                  setter = descriptor.getWriteMethod();
              if (setter == null) {
                  /*
                  if (debug >= 1)
                      System.out.println("    No setter method, skipping");
                  */
                  continue;
              }
              Class parameterTypes[] = setter.getParameterTypes();
              /*
              if (debug >= 1)
                  System.out.println("    Setter method is '" +
                                     setter.getName() + "(" +
                                     parameterTypes[0].getName() +
                                     (parameterTypes.length > 1 ?
                                      ", " + parameterTypes[1].getName() : "" )
                                     + ")'");
              */
              Class parameterType = parameterTypes[0];
              if (parameterTypes.length > 1)
                  parameterType = parameterTypes[1];      // Indexed setter
  
              // Convert the parameter value as required for this setter method
              Object parameters[] = new Object[1];
              if (parameterTypes[0].isArray()) {
                  if (value instanceof String) {
                      String values[] = new String[1];
                      values[0] = (String) value;
                      parameters[0] = ConvertUtils.convert((String[]) values,
                      parameterType);
                  } else if (value instanceof String[]) {
                      parameters[0] = ConvertUtils.convert((String[]) value,
                      parameterType);
                  } else {
                      parameters[0] = value;
                  }
              } else {
                  if (value instanceof String) {
                      parameters[0] = ConvertUtils.convert((String) value,
                      parameterType);
                  } else if (value instanceof String[]) {
                      parameters[0] = ConvertUtils.convert(((String[]) value)[0],
                      parameterType);
                  } else {
                      parameters[0] = value;
                  }
              }
  
              // Invoke the setter method
              /*
              if (debug >= 1)
                  System.out.println("    Setting to " +
                                     (parameters[0] == null ? "NULL" :
                                      "'" + parameters[0] + "'"));
              */
              try {
                  PropertyUtils.setProperty(bean, name, parameters[0]);
              } catch (NoSuchMethodException e) {
                  /*
                  if (debug >= 1) {
                      System.out.println("    CANNOT HAPPEN: " + e);
                      e.printStackTrace(System.out);
                  }
                  */
              }
  
          }
  
          /*
          if (debug >= 1)
              System.out.println("============================================");
          */
  
      }
  
  
  }
  
  
  
  1.1                  
jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/ConvertUtils.java
  
  Index: ConvertUtils.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/ConvertUtils.java,v
 1.1 2001/04/14 18:29:56 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2001/04/14 18:29:56 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  
  package org.apache.commons.beanutils;
  
  
  import java.lang.reflect.Array;
  
  
  /**
   * Utility methods for converting String values to objects of the specified
   * class.  If you specify a Java primitive type, or an array of a Java
   * primitive type, as a destination type, a scalar or array of the coresponding
   * Java wrapper class will be created instead.  If you attempt to convert an
   * Object or Object array of a non-String and non-primitive type, it will be
   * converted to a scalar String or array of Strings, as appropriate.
   *
   * @author Craig R. McClanahan
   * @author Ralph Schaer
   * @author Chris Audley
   * @version $Revision: 1.1 $ $Date: 2001/04/14 18:29:56 $
   */
  
  public class ConvertUtils {
  
  
      // ------------------------------------------------------ Static Properties
  
  
      /**
       * The default value for Boolean conversions.
       */
      private static Boolean defaultBoolean = Boolean.FALSE;
  
      public boolean getDefaultBoolean() {
          return (defaultBoolean.booleanValue());
      }
  
      public void setDefaultBoolean(boolean defaultBoolean) {
          this.defaultBoolean = new Boolean(defaultBoolean);
      }
  
  
      /**
       * The default value for Byte conversions.
       */
      private static Byte defaultByte = new Byte((byte) 0);
  
      public byte getDefaultByte() {
          return (defaultByte.byteValue());
      }
  
      public void setDefaultByte(byte defaultByte) {
          this.defaultByte = new Byte(defaultByte);
      }
  
  
      /**
       * The default value for Character conversions.
       */
      private static Character defaultCharacter = new Character(' ');
  
      public char getDefaultCharacter() {
          return (defaultCharacter.charValue());
      }
  
      public void setDefaultCharacter(char defaultCharacter) {
          this.defaultCharacter = new Character(defaultCharacter);
      }
  
  
      /**
       * The default value for Double conversions.
       */
      private static Double defaultDouble = new Double((double) 0.0);
  
      public double getDefaultDouble() {
          return (defaultDouble.doubleValue());
      }
  
      public void setDefaultDouble(double defaultDouble) {
          this.defaultDouble = new Double(defaultDouble);
      }
  
  
      /**
       * The default value for Float conversions.
       */
      private static Float defaultFloat = new Float((float) 0.0);
  
      public float getDefaultFloat() {
          return (defaultFloat.floatValue());
      }
  
      public void setDefaultFloat(float defaultFloat) {
          this.defaultFloat = new Float(defaultFloat);
      }
  
  
      /**
       * The default value for Integer conversions.
       */
      private static Integer defaultInteger = new Integer(0);
  
      public int getDefaultInteger() {
          return (defaultInteger.intValue());
      }
  
      public void setDefaultInteger(int defaultInteger) {
          this.defaultInteger = new Integer(defaultInteger);
      }
  
  
      /**
       * The default value for Long conversions.
       */
      private static Long defaultLong = new Long((long) 0);
  
      public long getDefaultLong() {
          return (defaultLong.longValue());
      }
  
      public void setDefaultLong(long defaultLong) {
          this.defaultLong = new Long(defaultLong);
      }
  
  
      /**
       * The default value for Short conversions.
       */
      private static Short defaultShort = new Short((short) 0);
  
      public short getDefaultShort() {
          return (defaultShort.shortValue());
      }
  
      public void setDefaultShort(short defaultShort) {
          this.defaultShort = new Short(defaultShort);
      }
  
  
      // ------------------------------------------------------- Static Variables
  
  
      /**
       * The Class object for java.lang.String.
       */
      private static Class stringClass = String.class;
  
  
      // --------------------------------------------------------- Public Classes
  
  
      /**
       * Convert the specified value into a String.  If the specified value
       * is an array, the first element (converted to a String) will be
       * returned.
       *
       * @param value Value to be converted (may be null)
       */
      public static String convert(Object value) {
  
          if (value == null) {
              return ((String) null);
          } else if (value.getClass().isArray()) {
              value = Array.get(value, 0);
              if (value == null)
                  return ((String) null);
              else
                  return (value.toString());
          } else {
              return (value.toString());
          }
  
      }
  
  
      /**
       * Convert the specified value to an object of the specified class (if
       * possible).  Otherwise, return a String representation of the value.
       * If you specify <code>type</code> as the name of a Java primitive
       * type, an instance of the corresponding wrapper class (initialized
       * to the correct value) is returned instead.
       *
       * @param value Value to be converted (may be null)
       * @param clazz Java class to be converted to (must be java.lang.String
       *  or one of the primitive type wrappers)
       */
      public static Object convert(String value, Class clazz) {
  
          if (clazz == stringClass) {
              if (value == null)
                  return ((String) null);
              else
                  return (value);
          } else if (clazz == Integer.TYPE) {
              return (convertInteger(value, defaultInteger));
          } else if (clazz == Boolean.TYPE) {
              return (convertBoolean(value, defaultBoolean));
          } else if (clazz == Long.TYPE) {
              return (convertLong(value, defaultLong));
          } else if (clazz == Double.TYPE) {
              return (convertDouble(value, defaultDouble));
          } else if (clazz == Character.TYPE) {
              return (convertCharacter(value, defaultCharacter));
          } else if (clazz == Byte.TYPE) {
              return (convertByte(value, defaultByte));
          } else if (clazz == Float.TYPE) {
              return (convertFloat(value, defaultFloat));
          } else if (clazz == Short.TYPE) {
              return (convertShort(value, defaultShort));
          } else if (clazz == Integer.class) {
              return (convertInteger(value, null));
          } else if (clazz == Boolean.class) {
              return (convertBoolean(value, null));
          } else if (clazz == Long.class) {
              return (convertLong(value, null));
          } else if (clazz == Double.class) {
              return (convertDouble(value, null));
          } else if (clazz == Character.class) {
              return (convertCharacter(value, null));
          } else if (clazz == Byte.class) {
              return (convertByte(value, null));
          } else if (clazz == Float.class) {
              return (convertFloat(value, null));
          } else if (clazz == Short.class) {
              return (convertShort(value, null));
          } else {
              if (value == null)
                  return ((String) null);
              else
                  return (value.toString());
          }
  
      }
  
  
      /**
       * Convert an array of specified values to an array of objects of the
       * specified class (if possible).  If you specify <code>type</code>
       * as one of the Java primitive types, an array of that type will be
       * returned; otherwise an array of the requested type (must be String
       * or a Java wrapper class for the primitive types) will be returned.
       *
       * @param value Value to be converted (may be null)
       * @param clazz Java array class to be converted to (must be String[],
       *  or an array of one of the Java primitive types)
       */
      public static Object convert(String values[], Class clazz) {
  
          Class type = clazz.getComponentType();
          if (type == stringClass) {
              if (values == null)
                  return ((String[]) null);
              else
                  return (values);
          }
  
          int len = values.length;
  
          if (type == Integer.TYPE) {
              int array[] = new int[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertInteger(values[i], defaultInteger).intValue();
              return (array);
          } else if (type == Boolean.TYPE) {
              boolean array[] = new boolean[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertBoolean(values[i], defaultBoolean).booleanValue();
              return (array);
          } else if (type == Long.TYPE) {
              long array[] = new long[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertLong(values[i], defaultLong).longValue();
              return (array);
          } else if (type == Double.TYPE) {
              double array[] = new double[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertDouble(values[i], defaultDouble).doubleValue();
              return (array);
          } else if (type == Character.TYPE) {
              char array[] = new char[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertCharacter(values[i], defaultCharacter).charValue();
              return (array);
          } else if (type == Byte.TYPE) {
              byte array[] = new byte[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertByte(values[i], defaultByte).byteValue();
              return (array);
          } else if (type == Float.TYPE) {
              float array[] = new float[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertFloat(values[i], defaultFloat).floatValue();
              return (array);
          } else if (type == Short.TYPE) {
              short array[] = new short[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertShort(values[i], defaultShort).shortValue();
              return (array);
          } else if (type == Integer.class) {
              Integer array[] = new Integer[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertInteger(values[i], null);
              return (array);
          } else if (type == Boolean.class) {
              Boolean array[] = new Boolean[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertBoolean(values[i], null);
              return (array);
          } else if (type == Long.class) {
              Long array[] = new Long[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertLong(values[i], null);
              return (array);
          } else if (type == Double.class) {
              Double array[] = new Double[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertDouble(values[i], null);
              return (array);
          } else if (type == Character.class) {
              Character array[] = new Character[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertCharacter(values[i], null);
              return (array);
          } else if (type == Byte.class) {
              Byte array[] = new Byte[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertByte(values[i], null);
              return (array);
          } else if (type == Float.class) {
              Float array[] = new Float[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertFloat(values[i], null);
              return (array);
          } else if (type == Short.class) {
              Short array[] = new Short[len];
              for (int i = 0; i < len; i++)
                  array[i] = convertShort(values[i], null);
              return (array);
          } else {
              if (values == null)
                  return ((String[]) null);
              else {
                  String array[] = new String[len];
                  for (int i = 0; i < len; i++)
                      array[i] = values[i].toString();
                  return (array);
              }
          }
  
      }
  
  
      // -------------------------------------------------------- Private Methods
  
  
      /**
       * Convert a String value to a corresponding Boolean value.
       *
       * @param value The string value to convert
       * @param defaultValue Default value to return on a conversion error
       */
      private static Boolean convertBoolean(String value, Boolean defaultValue) {
  
          if (value == null)
              return (defaultValue);
          else if (value.equalsIgnoreCase("yes") ||
                   value.equalsIgnoreCase("true") ||
                   value.equalsIgnoreCase("on"))
              return (Boolean.TRUE);
          else if (value.equalsIgnoreCase("no") ||
                   value.equalsIgnoreCase("false") ||
                   value.equalsIgnoreCase("off"))
              return (Boolean.FALSE);
          else
              return (defaultValue);
  
      }
  
  
      /**
       * Convert a String value to a corresponding Byte value.
       *
       * @param value The string value to convert
       * @param defaultValue Default value to return on a conversion error
       */
      private static Byte convertByte(String value, Byte defaultValue) {
  
          try {
              return (new Byte(value));
          } catch (NumberFormatException e) {
              return (defaultValue);
          }
  
      }
  
  
      /**
       * Convert a String value to a corresponding Character value.
       *
       * @param value The string value to convert
       * @param defaultValue Default value to return on a conversion error
       */
      private static Character convertCharacter(String value,
                                                Character defaultValue) {
  
          if (value == null)
              return (defaultValue);
          else if (value.length() == 0)
              return (new Character(' '));
          else
              return (defaultValue);
  
      }
  
  
      /**
       * Convert a String value to a corresponding Double value.
       *
       * @param value The string value to convert
       * @param defaultValue Default value to return on a conversion error
       */
      private static Double convertDouble(String value,
                                          Double defaultValue) {
  
          try {
              return (new Double(value));
          } catch (NumberFormatException e) {
              return (defaultValue);
          }
  
      }
  
  
      /**
       * Convert a String value to a corresponding Float value.
       *
       * @param value The string value to convert
       * @param defaultValue Default value to return on a conversion error
       */
      private static Float convertFloat(String value,
                                        Float defaultValue) {
  
          try {
              return (new Float(value));
          } catch (NumberFormatException e) {
              return (defaultValue);
          }
  
      }
  
  
      /**
       * Convert a String value to a corresponding Integer value.
       *
       * @param value The string value to convert
       * @param defaultValue Default value to return on a conversion error
       */
      private static Integer convertInteger(String value,
                                            Integer defaultValue) {
  
          try {
              return (new Integer(value));
          } catch (NumberFormatException e) {
              return (defaultValue);
          }
  
      }
  
  
      /**
       * Convert a String value to a corresponding Long value.
       *
       * @param value The string value to convert
       * @param defaultValue Default value to return on a conversion error
       */
      private static Long convertLong(String value, Long defaultValue) {
  
          try {
              return (new Long(value));
          } catch (NumberFormatException e) {
              return (defaultValue);
          }
  
      }
  
  
      /**
       * Convert a String value to a corresponding Short value.
       *
       * @param value The string value to convert
       * @param defaultValue Default value to return on a conversion error
       */
      private static Short convertShort(String value, Short defaultValue) {
  
          try {
              return (new Short(value));
          } catch (NumberFormatException e) {
              return (defaultValue);
          }
  
      }
  
  
  }
  
  
  
  1.1                  
jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/PropertyUtils.java
  
  Index: PropertyUtils.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/PropertyUtils.java,v
 1.1 2001/04/14 18:29:56 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2001/04/14 18:29:56 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  
  package org.apache.commons.beanutils;
  
  
  import java.beans.BeanInfo;
  import java.beans.IndexedPropertyDescriptor;
  import java.beans.IntrospectionException;
  import java.beans.Introspector;
  import java.beans.PropertyDescriptor;
  import java.lang.reflect.Array;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.util.HashMap;
  
  
  /**
   * Utility methods for using Java Reflection APIs to facilitate generic
   * property getter and setter operations on Java objects.  Much of this
   * code was originally included in <code>BeanUtils</code>, but has been
   * separated because of the volume of code involved.
   * <p>
   * In general, the objects that are examined and modified using these
   * methods are expected to conform to the property getter and setter method
   * naming conventions described in the JavaBeans Specification (Version 1.0.1).
   * No data type conversions are performed, and there are no usage of any
   * <code>PropertyEditor</code> classes that have been registered, although
   * a convenient way to access the registered classes themselves is included.
   * <p>
   * For the purposes of this class, three formats for referencing a particular
   * property value of a bean are defined, with the layout of an identifying
   * String in parentheses:
   * <ul>
   * <li><strong>Simple (<code>name</code>)</strong> - The specified
   *     <code>name</code> identifies an individual property of a particular
   *     JavaBean.  The name of the actual getter or setter method to be used
   *     is determined using standard JavaBeans instrospection, so that (unless
   *     overridden by a <code>BeanInfo</code> class, a property named "xyz"
   *     will have a getter method named <code>getXyz()</code> or (for boolean
   *     properties only) <code>isXyz()</code>, and a setter method named
   *     <code>setXyz()</code>.</li>
   * <li><strong>Nested (<code>name1.name2.name3</code>)</strong> The first
   *     name element is used to select a property getter, as for simple
   *     references above.  The object returned for this property is then
   *     consulted, using the same approach, for a property getter for a
   *     property named <code>name2</code>, and so on.  The property value that
   *     is ultimately retrieved or modified is the one identified by the
   *     last name element.</li>
   * <li><strong>Indexed (<code>name[index]</code>)</strong> - The underlying
   *     property value is assumed to be an array, or this JavaBean is assumed
   *     to have indexed property getter and setter methods.  The appropriate
   *     (zero-relative) entry in the array is selected.</li>
   * <li><strong>Combined (<code>name1.name2[index].name3</strong> - Various
   *     forms combining nested and indexed references are also supported.</li>
   * </ul>
   *
   * @author Craig R. McClanahan
   * @author Ralph Schaer
   * @author Chris Audley
   * @version $Revision: 1.1 $ $Date: 2001/04/14 18:29:56 $
   */
  
  public class PropertyUtils {
  
  
      // ----------------------------------------------------- Manifest Constants
  
  
      /**
       * The delimiter that preceeds the zero-relative subscript for an
       * indexed reference.
       */
      public static final char INDEXED_DELIM = '[';
  
  
      /**
       * The delimiter that follows the zero-relative subscript for an
       * indexed reference.
       */
      public static final char INDEXED_DELIM2 = ']';
  
  
      /**
       * The delimiter that separates the components of a nested reference.
       */
      public static final char NESTED_DELIM = '.';
  
  
      // ------------------------------------------------------- Static Variables
  
  
      /**
       * The debugging detail level for this component.
       */
      private static int debug = 0;
  
      public static int getDebug() {
          return (debug);
      }
  
      public static void setDebug(int newDebug) {
          debug = newDebug;
      }
  
  
      /**
       * The cache of PropertyDescriptor arrays for beans we have already
       * introspected, keyed by the fully qualified class name of this object.
       */
      private static HashMap descriptorsCache = new HashMap();
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Copy property values from the "origin" bean to the "destination" bean
       * for all cases where the property names are the same (even though the
       * actual getter and setter methods might have been customized via
       * <code>BeanInfo</code> classes).  No conversions are performed on the
       * actual property values -- it is assumed that the values retrieved from
       * the origin bean are assignment-compatible with the types expected by
       * the destination bean.
       *
       * @param dest Destination bean whose properties are modified
       * @param orig Origin bean whose properties are retrieved
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static void copyProperties(Object dest, Object orig)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
        PropertyDescriptor origDescriptors[] = getPropertyDescriptors(orig);
        for (int i = 0; i < origDescriptors.length; i++) {
            String name = origDescriptors[i].getName();
            if (getPropertyDescriptor(dest, name) != null) {
                Object value = getSimpleProperty(orig, name);
                  try {
                      setSimpleProperty(dest, name, value);
                  } catch (NoSuchMethodException e) {
                      ;   // Skip non-matching property
                  }
            }
        }
  
      }
  
  
      /**
       * Return the value of the specified indexed property of the specified
       * bean, with no type conversions.  The zero-relative index of the
       * required value must be included (in square brackets) as a suffix to
       * the property name, or <code>IllegalArgumentException</code> will be
       * thrown.
       *
       * @param bean Bean whose property is to be extracted
       * @param name <code>propertyname[index]</code> of the property value
       *  to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static Object getIndexedProperty(Object bean, String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
        // Identify the index of the requested individual property
          int delim = name.indexOf(INDEXED_DELIM);
          int delim2 = name.indexOf(INDEXED_DELIM2);
          if ((delim < 0) || (delim2 <= delim))
            throw new IllegalArgumentException("Invalid indexed property '" +
                                               name + "'");
        int index = -1;
        try {
            String subscript = name.substring(delim + 1, delim2);
            index = Integer.parseInt(subscript);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Invalid indexed property '" +
                                               name + "'");
        }
        name = name.substring(0, delim);
  
        // Request the specified indexed property value
        return (getIndexedProperty(bean, name, index));
  
      }
  
  
      /**
       * Return the value of the specified indexed property of the specified
       * bean, with no type conversions.
       *
       * @param bean Bean whose property is to be extracted
       * @param name Simple property name of the property value to be extracted
       * @param index Index of the property value to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static Object getIndexedProperty(Object bean,
                                            String name, int index)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
        // Retrieve the property descriptor for the specified property
        PropertyDescriptor descriptor =
            getPropertyDescriptor(bean, name);
        if (descriptor == null)
            throw new NoSuchMethodException("Unknown property '" +
                                            name + "'");
  
        // Call the indexed getter method if there is one
        if (descriptor instanceof IndexedPropertyDescriptor) {
            Method readMethod = ((IndexedPropertyDescriptor) descriptor).
                getIndexedReadMethod();
            if (readMethod != null) {
                Object subscript[] = new Object[1];
                subscript[0] = new Integer(index);
                return (readMethod.invoke(bean, subscript));
            }
        }
  
        // Otherwise, the underlying property must be an array
          Method readMethod = getReadMethod(descriptor);
        if (readMethod == null)
            throw new NoSuchMethodException("Property '" + name +
                                            "' has no getter method");
  
        // Call the property getter and return the value
        Object value = readMethod.invoke(bean, new Object[0]);
        if (!value.getClass().isArray())
            throw new IllegalArgumentException("Property '" + name +
                                               "' is not indexed");
        return (Array.get(value, index));
  
      }
  
  
      /**
       * Return the value of the (possibly nested) property of the specified
       * name, for the specified bean, with no type conversions.
       *
       * @param bean Bean whose property is to be extracted
       * @param name Possibly nested name of the property to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception IllegalArgumentException if a nested reference to a
       *  property returns null
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static Object getNestedProperty(Object bean, String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
        while (true) {
            int delim = name.indexOf(NESTED_DELIM);
            if (delim < 0)
                break;
            String next = name.substring(0, delim);
            if (next.indexOf(INDEXED_DELIM) >= 0)
                bean = getIndexedProperty(bean, next);
            else
                bean = getSimpleProperty(bean, next);
            if (bean == null)
                throw new IllegalArgumentException
                    ("Null property value for '" +
                     name.substring(0, delim) + "'");
            name = name.substring(delim + 1);
        }
  
        if (name.indexOf(INDEXED_DELIM) >= 0)
            return (getIndexedProperty(bean, name));
        else
            return (getSimpleProperty(bean, name));
  
      }
  
  
      /**
       * Return the value of the specified property of the specified bean,
       * no matter which property reference format is used, with no
       * type conversions.
       *
       * @param bean Bean whose property is to be extracted
       * @param name Possibly indexed and/or nested name of the property
       *  to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static Object getProperty(Object bean, String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
        return (getNestedProperty(bean, name));
  
      }
  
  
      /**
       * Retrieve the property descriptor for the specified property of the
       * specified bean, or return <code>null</code> if there is no such
       * descriptor.  This method resolves indexed and nested property
       * references in the same manner as other methods in this class, except
       * that if the last (or only) name element is indexed, the descriptor
       * for the last resolved property itself is returned.
       *
       * @param bean Bean for which a property descriptor is requested
       * @param name Possibly indexed and/or nested name of the property for
       *  which a property descriptor is requested
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception IllegalArgumentException if a nested reference to a
       *  property returns null
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static PropertyDescriptor getPropertyDescriptor(Object bean,
                                                           String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
        // Resolve nested references
        while (true) {
            int period = name.indexOf(NESTED_DELIM);
            if (period < 0)
                break;
            String next = name.substring(0, period);
            if (next.indexOf(INDEXED_DELIM) >= 0)
                bean = getIndexedProperty(bean, next);
            else
                bean = getSimpleProperty(bean, next);
            if (bean == null)
                throw new IllegalArgumentException
                    ("Null property value for '" +
                     name.substring(0, period) + "'");
            name = name.substring(period + 1);
        }
  
        // Remove any subscript from the final name value
        int left = name.indexOf(INDEXED_DELIM);
        if (left >= 0)
            name = name.substring(0, left);
  
        // Look up and return this property from our cache
        if ((bean == null) || (name == null))
            return (null);
        PropertyDescriptor descriptors[] = getPropertyDescriptors(bean);
        if (descriptors == null)
            return (null);
        for (int i = 0; i < descriptors.length; i++) {
            if (name.equals(descriptors[i].getName()))
                return (descriptors[i]);
        }
        return (null);
  
      }
  
  
      /**
       * Retrieve the property descriptors for the specified bean, introspecting
       * and caching them the first time a particular bean class is encountered.
       *
       * @param bean Bean for which property descriptors are requested
       */
      public static PropertyDescriptor[] getPropertyDescriptors(Object bean) {
  
        if (bean == null)
            return (new PropertyDescriptor[0]);
  
        // Look up any cached descriptors for this bean class
        String beanClassName = bean.getClass().getName();
        PropertyDescriptor descriptors[] = null;
          synchronized (descriptorsCache) {
              descriptors =
                  (PropertyDescriptor[]) descriptorsCache.get(beanClassName);
          }
        if (descriptors != null)
            return (descriptors);
  
        // Introspect the bean and cache the generated descriptors
        BeanInfo beanInfo = null;
        try {
            beanInfo = Introspector.getBeanInfo(bean.getClass());
        } catch (IntrospectionException e) {
            return (new PropertyDescriptor[0]);
        }
        descriptors = beanInfo.getPropertyDescriptors();
        if (descriptors == null)
            descriptors = new PropertyDescriptor[0];
          synchronized (descriptorsCache) {
              descriptorsCache.put(beanClassName, descriptors);
          }
        return (descriptors);
  
      }
  
  
      /**
       * Return the Java Class repesenting the property editor class that has
       * been registered for this property (if any).  This method follows the
       * same name resolution rules used by <code>getPropertyDescriptor()</code>,
       * so if the last element of a name reference is indexed, the property
       * editor for the underlying property's class is returned.
       * <p>
       * Note that <code>null</code> will be returned if there is no property,
       * or if there is no registered property editor class.  Because this
       * return value is ambiguous, you should determine the existence of the
       * property itself by other means.
       *
       * @param bean Bean for which a property descriptor is requested
       * @param name Possibly indexed and/or nested name of the property for
       *  which a property descriptor is requested
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception IllegalArgumentException if a nested reference to a
       *  property returns null
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static Class getPropertyEditorClass(Object bean, String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
        PropertyDescriptor descriptor =
            getPropertyDescriptor(bean, name);
        if (descriptor != null)
            return (descriptor.getPropertyEditorClass());
        else
            return (null);
  
      }
  
  
      /**
       * Return the Java Class representing the property type of the specified
       * property, or <code>null</code> if there is no such property for the
       * specified bean.  This method follows the same name resolution rules
       * used by <code>getPropertyDescriptor()</code>, so if the last element
       * of a name reference is indexed, the type of the property itself will
       * be returned.  If the last (or only) element has no property with the
       * specified name, <code>null</code> is returned.
       *
       * @param bean Bean for which a property descriptor is requested
       * @param name Possibly indexed and/or nested name of the property for
       *  which a property descriptor is requested
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception IllegalArgumentException if a nested reference to a
       *  property returns null
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static Class getPropertyType(Object bean, String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
        PropertyDescriptor descriptor =
            getPropertyDescriptor(bean, name);
        if (descriptor == null)
              return (null);
          else if (descriptor instanceof IndexedPropertyDescriptor)
              return (((IndexedPropertyDescriptor) descriptor).
                      getIndexedPropertyType());
          else
            return (descriptor.getPropertyType());
  
      }
  
  
      /**
       * Return the value of the specified simple property of the specified
       * bean, with no type conversions.
       *
       * @param bean Bean whose property is to be extracted
       * @param name Name of the property to be extracted
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception IllegalArgumentException if the property name
       *  is nested or indexed
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static Object getSimpleProperty(Object bean, String name)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
          // Validate the syntax of the property name
          if (name.indexOf(NESTED_DELIM) >= 0)
              throw new IllegalArgumentException
                  ("Nested property names are not allowed");
          else if (name.indexOf(INDEXED_DELIM) >= 0)
              throw new IllegalArgumentException
                  ("Indexed property names are not allowed");
  
        // Retrieve the property getter method for the specified property
        PropertyDescriptor descriptor =
            getPropertyDescriptor(bean, name);
        if (descriptor == null)
            throw new NoSuchMethodException("Unknown property '" +
                                            name + "'");
          Method readMethod = getReadMethod(descriptor);
        if (readMethod == null)
            throw new NoSuchMethodException("Property '" + name +
                                            "' has no getter method");
  
        // Call the property getter and return the value
        Object value = readMethod.invoke(bean, new Object[0]);
        return (value);
  
      }
  
  
      /**
       * Set the value of the specified indexed property of the specified
       * bean, with no type conversions.  The zero-relative index of the
       * required value must be included (in square brackets) as a suffix to
       * the property name, or <code>IllegalArgumentException</code> will be
       * thrown.
       *
       * @param bean Bean whose property is to be modified
       * @param name <code>propertyname[index]</code> of the property value
       *  to be modified
       * @param value Value to which the specified property element
       *  should be set
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static void setIndexedProperty(Object bean, String name,
                                          Object value)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
          if (debug >= 1)
              System.out.println("setIndexedProperty('" + bean + ", " +
                                 name + ", " + value + ")");
  
        // Identify the index of the requested individual property
        int delim = name.indexOf(INDEXED_DELIM);
          int delim2 = name.indexOf(INDEXED_DELIM2);
          if ((delim < 0) || (delim2 <= delim))
            throw new IllegalArgumentException("Invalid indexed property '" +
                                               name + "'");
        int index = -1;
        try {
            String subscript = name.substring(delim + 1, delim2);
            index = Integer.parseInt(subscript);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Invalid indexed property '" +
                                               name + "'");
        }
        name = name.substring(0, delim);
  
        // Set the specified indexed property value
        setIndexedProperty(bean, name, index, value);
  
      }
  
  
      /**
       * Set the value of the specified indexed property of the specified
       * bean, with no type conversions.
       *
       * @param bean Bean whose property is to be set
       * @param name Simple property name of the property value to be set
       * @param index Index of the property value to be set
       * @param value Value to which the indexed property element is to be set
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static void setIndexedProperty(Object bean, String name,
                                          int index, Object value)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
          if (debug >= 1)
              System.out.println("setIndexedProperty('" + bean + ", " +
                                 name + ", " + index + ", " + value + ")");
  
        // Retrieve the property descriptor for the specified property
        PropertyDescriptor descriptor =
            getPropertyDescriptor(bean, name);
        if (descriptor == null)
            throw new NoSuchMethodException("Unknown property '" +
                                            name + "'");
  
        // Call the indexed setter method if there is one
        if (descriptor instanceof IndexedPropertyDescriptor) {
            Method writeMethod = ((IndexedPropertyDescriptor) descriptor).
                getIndexedWriteMethod();
            if (writeMethod != null) {
                Object subscript[] = new Object[2];
                subscript[0] = new Integer(index);
                subscript[1] = value;
                writeMethod.invoke(bean, subscript);
                  return;
            }
        }
  
        // Otherwise, the underlying property must be an array
          Method readMethod = descriptor.getReadMethod();
        if (readMethod == null)
            throw new NoSuchMethodException("Property '" + name +
                                            "' has no getter method");
  
        // Call the property getter to get the array
        Object array = readMethod.invoke(bean, new Object[0]);
        if (!array.getClass().isArray())
            throw new IllegalArgumentException("Property '" + name +
                                               "' is not indexed");
  
        // Modify the specified value
        Array.set(array, index, value);
  
      }
  
  
      /**
       * Set the value of the (possibly nested) property of the specified
       * name, for the specified bean, with no type conversions.
       *
       * @param bean Bean whose property is to be modified
       * @param name Possibly nested name of the property to be modified
       * @param value Value to which the property is to be set
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception IllegalArgumentException if a nested reference to a
       *  property returns null
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static void setNestedProperty(Object bean,
                                         String name, Object value)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
          if (debug >= 1)
              System.out.println("setNestedProperty('" + bean + ", " +
                                 name + ", " + value + ")");
  
        while (true) {
            int delim = name.indexOf(NESTED_DELIM);
            if (delim < 0)
                break;
            String next = name.substring(0, delim);
            if (next.indexOf(INDEXED_DELIM) >= 0)
                bean = getIndexedProperty(bean, next);
            else
                bean = getSimpleProperty(bean, next);
            if (bean == null)
                throw new IllegalArgumentException
                    ("Null property value for '" +
                     name.substring(0, delim) + "'");
            name = name.substring(delim + 1);
        }
  
        if (name.indexOf(INDEXED_DELIM) >= 0)
            setIndexedProperty(bean, name, value);
        else
            setSimpleProperty(bean, name, value);
  
      }
  
  
      /**
       * Set the value of the specified property of the specified bean,
       * no matter which property reference format is used, with no
       * type conversions.
       *
       * @param bean Bean whose property is to be modified
       * @param name Possibly indexed and/or nested name of the property
       *  to be modified
       * @param value Value to which this property is to be set
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static void setProperty(Object bean, String name, Object value)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
        setNestedProperty(bean, name, value);
  
      }
  
  
      /**
       * Set the value of the specified simple property of the specified bean,
       * with no type conversions.
       *
       * @param bean Bean whose property is to be modified
       * @param name Name of the property to be modified
       * @param value Value to which the property should be set
       *
       * @exception IllegalAccessException if the caller does not have
       *  access to the property accessor method
       * @exception IllegalArgumentException if the property name is
       *  nested or indexed
       * @exception InvocationTargetException if the property accessor method
       *  throws an exception
       * @exception NoSuchMethodException if an accessor method for this
       *  propety cannot be found
       */
      public static void setSimpleProperty(Object bean,
                                         String name, Object value)
        throws IllegalAccessException, InvocationTargetException,
               NoSuchMethodException {
  
          if (debug >= 1)
              System.out.println("setSimpleProperty('" + bean + ", " +
                                 name + ", " + value + ")");
  
          // Validate the syntax of the property name
          if (name.indexOf(NESTED_DELIM) >= 0)
              throw new IllegalArgumentException
                  ("Nested property names are not allowed");
          else if (name.indexOf(INDEXED_DELIM) >= 0)
              throw new IllegalArgumentException
                  ("Indexed property names are not allowed");
  
        // Retrieve the property setter method for the specified property
        PropertyDescriptor descriptor =
            getPropertyDescriptor(bean, name);
        if (descriptor == null)
            throw new NoSuchMethodException("Unknown property '" +
                                            name + "'");
          Method writeMethod = getWriteMethod(descriptor);
        if (writeMethod == null)
            throw new NoSuchMethodException("Property '" + name +
                                            "' has no setter method");
  
        // Call the property setter method
        Object values[] = new Object[1];
        values[0] = value;
        writeMethod.invoke(bean, values);
  
      }
  
  
      // -------------------------------------------------------- Private Methods
  
  
      /**
       * Return an accessible method (that is, one that can be invoked via
       * reflection) that implements the specified Method.  If no such method
       * can be found, return <code>null</code>.
       *
       * @param method The method that we wish to call
       */
      private static Method getAccessibleMethod(Method method) {
  
          // Make sure we have a method to check
          if (method == null) {
              return (null);
          }
  
          // If the requested method is not public we cannot call it
          if (!Modifier.isPublic(method.getModifiers())) {
              return (null);
          }
  
          // If the declaring class is public, we are done
          Class clazz = method.getDeclaringClass();
          if (Modifier.isPublic(clazz.getModifiers())) {
              return (method);
          }
  
          // Check the implemented interfaces
          String methodName = method.getName();
          Class[] parameterTypes = method.getParameterTypes();
          Class[] interfaces = clazz.getInterfaces();
          for (int i = 0; i < interfaces.length; i++) {
              // Is this interface public?
              if (!Modifier.isPublic(interfaces[i].getModifiers())) {
                  continue;
              }
              // Does the method exist on this interface?
              try {
                  method = interfaces[i].getDeclaredMethod(methodName,
                                                           parameterTypes);
              } catch (NoSuchMethodException e) {
                  continue;
              }
              // We have found what we are looking for
              return (method);
          }
  
          // We are out of luck
          return (null);
  
      }
  
  
      /**
       * Return an accessible property getter method for this property,
       * if there is one; otherwise return <code>null</code>.
       *
       * @param descriptor Property descriptor to return a getter for
       */
      private static Method getReadMethod(PropertyDescriptor descriptor) {
  
          return (getAccessibleMethod(descriptor.getReadMethod()));
  
      }
  
  
      /**
       * Return an accessible property setter method for this property,
       * if there is one; otherwise return <code>null</code>.
       *
       * @param descriptor Property descriptor to return a setter for
       */
      private static Method getWriteMethod(PropertyDescriptor descriptor) {
  
          return (getAccessibleMethod(descriptor.getWriteMethod()));
  
      }
  
  
  }
  
  
  
  1.1                  
jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/package.html
  
  Index: package.html
  ===================================================================
  <html>
  <head>
  <title>Package Documentation for org.apache.commons.beanutils Package</title>
  </head>
  <body bgcolor="white">
  <p>The <em>Bean Utilties</em> component of the Jakarta Commons subproject
  offers low-level utility classes that assist in getting and setting property
  values on Java classes that follow the naming design patterns outlined in the
  JavaBeans Specification.</p>
  
  </body>
  </html>
  
  
  

Reply via email to