BeanPropertyDescriptor.java |
/* * The Apache Software License, Version 1.1 * * * Copyright (c) 2001-2003 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 acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Axis" 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 apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * 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.jboss.axis.utils; import org.jboss.logging.Logger; import java.beans.IndexedPropertyDescriptor; import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * This class represents a field/property in a value type (a class with either * bean-style getters/setters or public fields). * <p/> * It is essentially a thin wrapper around the PropertyDescriptor from the * JavaBean utilities. We wrap it with this class so that we can create * the subclass FieldPropertyDescriptor and access public fields (who * wouldn't have PropertyDescriptors normally) via the same interface. * <p/> * There are also some interesting tricks where indexed properties are * concerned, mostly involving the fact that we manage the arrays here * rather than relying on the value type class to do it itself. * * @author Rich Scheuerle <scheu@us.ibm.com> * @author Glen Daniels (gdaniels@apache.org) */ public class BeanPropertyDescriptor { private static Logger log = Logger.getLogger(BeanPropertyDescriptor.class.getName()); protected PropertyDescriptor myPD = null; protected static final Object[] noArgs = new Object[]{}; /** * Constructor (takes a PropertyDescriptor) * * @param pd */ public BeanPropertyDescriptor(PropertyDescriptor pd) { myPD = pd; } /** * Protected constructor for use by our children */ protected BeanPropertyDescriptor() { } /** * Get our property name. */ public String getName() { return myPD.getName(); } /** * Query if property is readable * * @return true if readable */ public boolean isReadable() { return (myPD.getReadMethod() != null); } /** * Query if property is writeable * * @return true if writeable */ public boolean isWriteable() { return (myPD.getWriteMethod() != null); } /** * Query if property is indexed. * * @return true if indexed methods exist */ public boolean isIndexed() { return (myPD instanceof IndexedPropertyDescriptor); } /** * Get the property value * * @param obj is the object * @return the entire propery value */ public Object get(Object obj) throws InvocationTargetException, IllegalAccessException { if (obj == null) throw new IllegalArgumentException("Target object cannot be null"); Method readMethod = myPD.getReadMethod(); log.debug("get: [method=" + readMethod + "]"); if (readMethod != null) { Object retObj = readMethod.invoke(obj, noArgs); log.debug("got: " + retObj); return retObj; } throw new IllegalAccessException(Messages.getMessage("badGetter00")); } /** * Set the property value * * @param obj is the object * @param newValue is the new value */ public void set(Object obj, Object newValue) throws InvocationTargetException, IllegalAccessException { if (obj == null) throw new IllegalArgumentException("Target object cannot be null"); Method writeMethod = myPD.getWriteMethod(); log.debug("set: [val=" + newValue + ",method=" + writeMethod + "]"); if (writeMethod != null) { writeMethod.invoke(obj, new Object[]{newValue}); } else { throw new IllegalAccessException(Messages.getMessage("badSetter00")); } } /** * Get an indexed property * * @param obj is the object * @param i the index * @return the object at the indicated index */ public Object get(Object obj, int i) throws InvocationTargetException, IllegalAccessException { if (obj == null) throw new IllegalArgumentException("Target object cannot be null"); if (!isIndexed()) { return Array.get(get(obj), i); } else { IndexedPropertyDescriptor id = (IndexedPropertyDescriptor)myPD; Method readMethod = id.getIndexedReadMethod(); log.debug("get: [method=" + readMethod + ",index=" + i + "]"); Object retObj = readMethod.invoke(obj, new Object[]{new Integer(i)}); log.debug("got: " + retObj); return retObj; } } /** * Set an indexed property value * * @param obj is the object * @param i the index * @param newValue is the new value */ public void set(Object obj, int i, Object newValue) throws InvocationTargetException, IllegalAccessException { if (obj == null) throw new IllegalArgumentException("Target object cannot be null"); // Set the new value if (isIndexed()) { IndexedPropertyDescriptor id = (IndexedPropertyDescriptor)myPD; growArrayToSize(obj, id.getIndexedPropertyType(), i); id.getIndexedWriteMethod().invoke(obj, new Object[]{ new Integer(i), newValue}); } else { Object array = get(obj); if (array == null || Array.getLength(array) <= i) { Class componentType = getType().getComponentType(); growArrayToSize(obj, componentType, i); array = get(obj); } Array.set(array, i, newValue); } } /** * Grow the array * * @param obj * @param componentType * @param i * @throws InvocationTargetException * @throws IllegalAccessException */ protected void growArrayToSize(Object obj, Class componentType, int i) throws InvocationTargetException, IllegalAccessException { if (obj == null) throw new IllegalArgumentException("Target object cannot be null"); // Get the entire array and make sure it is large enough Object array = get(obj); if (array == null || Array.getLength(array) <= i) { // Construct a larger array of the same type Object newArray = Array.newInstance(componentType, i + 1); // Copy over the old elements if (array != null) { System.arraycopy(array, 0, newArray, 0, Array.getLength(array)); } // Set the object to use the larger array set(obj, newArray); } } /** * Get the type of a property * * @return the type of the property */ public Class getType() { if (isIndexed()) { return ((IndexedPropertyDescriptor)myPD).getIndexedPropertyType(); } else { return myPD.getPropertyType(); } } }
BeanPropertyDescriptor.java |