523 lines · 21.5 KB · Java
RawDownload
/* * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.beans; import java.lang.ref.Reference;import java.lang.reflect.Method; /** * An IndexedPropertyDescriptor describes a property that acts like an * array and has an indexed read and/or indexed write method to access * specific elements of the array. * <p> * An indexed property may also provide simple non-indexed read and write * methods.  If these are present, they read and write arrays of the type * returned by the indexed read method. */ public class IndexedPropertyDescriptor extends PropertyDescriptor {     private Reference<Class> indexedPropertyTypeRef;    private Reference<Method> indexedReadMethodRef;    private Reference<Method> indexedWriteMethodRef;     private String indexedReadMethodName;    private String indexedWriteMethodName;     /**     * This constructor constructs an IndexedPropertyDescriptor for a property     * that follows the standard Java conventions by having getFoo and setFoo     * accessor methods, for both indexed access and array access.     * <p>     * Thus if the argument name is "fred", it will assume that there     * is an indexed reader method "getFred", a non-indexed (array) reader     * method also called "getFred", an indexed writer method "setFred",     * and finally a non-indexed writer method "setFred".     *     * @param propertyName The programmatic name of the property.     * @param beanClass The Class object for the target bean.     * @exception IntrospectionException if an exception occurs during     *              introspection.     */    public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass)                throws IntrospectionException {        this(propertyName, beanClass,             Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName),             Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName),             Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName),             Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName));    }     /**     * This constructor takes the name of a simple property, and method     * names for reading and writing the property, both indexed     * and non-indexed.     *     * @param propertyName The programmatic name of the property.     * @param beanClass  The Class object for the target bean.     * @param readMethodName The name of the method used for reading the property     *           values as an array.  May be null if the property is write-only     *           or must be indexed.     * @param writeMethodName The name of the method used for writing the property     *           values as an array.  May be null if the property is read-only     *           or must be indexed.     * @param indexedReadMethodName The name of the method used for reading     *          an indexed property value.     *          May be null if the property is write-only.     * @param indexedWriteMethodName The name of the method used for writing     *          an indexed property value.     *          May be null if the property is read-only.     * @exception IntrospectionException if an exception occurs during     *              introspection.     */    public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass,                String readMethodName, String writeMethodName,                String indexedReadMethodName, String indexedWriteMethodName)                throws IntrospectionException {        super(propertyName, beanClass, readMethodName, writeMethodName);         this.indexedReadMethodName = indexedReadMethodName;        if (indexedReadMethodName != null && getIndexedReadMethod() == null) {            throw new IntrospectionException("Method not found: " + indexedReadMethodName);        }         this.indexedWriteMethodName = indexedWriteMethodName;        if (indexedWriteMethodName != null && getIndexedWriteMethod() == null) {            throw new IntrospectionException("Method not found: " + indexedWriteMethodName);        }        // Implemented only for type checking.        findIndexedPropertyType(getIndexedReadMethod(), getIndexedWriteMethod());    }     /**     * This constructor takes the name of a simple property, and Method     * objects for reading and writing the property.     *     * @param propertyName The programmatic name of the property.     * @param readMethod The method used for reading the property values as an array.     *          May be null if the property is write-only or must be indexed.     * @param writeMethod The method used for writing the property values as an array.     *          May be null if the property is read-only or must be indexed.     * @param indexedReadMethod The method used for reading an indexed property value.     *          May be null if the property is write-only.     * @param indexedWriteMethod The method used for writing an indexed property value.     *          May be null if the property is read-only.     * @exception IntrospectionException if an exception occurs during     *              introspection.     */    public IndexedPropertyDescriptor(String propertyName, Method readMethod, Method writeMethod,                                            Method indexedReadMethod, Method indexedWriteMethod)                throws IntrospectionException {        super(propertyName, readMethod, writeMethod);         setIndexedReadMethod0(indexedReadMethod);        setIndexedWriteMethod0(indexedWriteMethod);         // Type checking        setIndexedPropertyType(findIndexedPropertyType(indexedReadMethod, indexedWriteMethod));    }     /**     * Creates <code>PropertyDescriptor</code> for the specified bean     * with the specified name and methods to read/write the property value.     *     * @param bean          the type of the target bean     * @param base          the base name of the property (the rest of the method name)     * @param read          the method used for reading the property value     * @param write         the method used for writing the property value     * @param readIndexed   the method used for reading an indexed property value     * @param writeIndexed  the method used for writing an indexed property value     * @exception IntrospectionException if an exception occurs during introspection     *     * @since 1.7     */    IndexedPropertyDescriptor(Class<?> bean, String base, Method read, Method write, Method readIndexed, Method writeIndexed) throws IntrospectionException {        super(bean, base, read, write);         setIndexedReadMethod0(readIndexed);        setIndexedWriteMethod0(writeIndexed);         // Type checking        setIndexedPropertyType(findIndexedPropertyType(readIndexed, writeIndexed));    }     /**     * Gets the method that should be used to read an indexed     * property value.     *     * @return The method that should be used to read an indexed     * property value.     * May return null if the property isn't indexed or is write-only.     */    public synchronized Method getIndexedReadMethod() {        Method indexedReadMethod = getIndexedReadMethod0();        if (indexedReadMethod == null) {            Class cls = getClass0();            if (cls == null ||                (indexedReadMethodName == null && indexedReadMethodRef == null)) {                // the Indexed readMethod was explicitly set to null.                return null;            }            if (indexedReadMethodName == null) {                Class type = getIndexedPropertyType0();                if (type == boolean.class || type == null) {                    indexedReadMethodName = Introspector.IS_PREFIX + getBaseName();                } else {                    indexedReadMethodName = Introspector.GET_PREFIX + getBaseName();                }            }             Class[] args = { int.class };            indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);            if (indexedReadMethod == null) {                // no "is" method, so look for a "get" method.                indexedReadMethodName = Introspector.GET_PREFIX + getBaseName();                indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);            }            setIndexedReadMethod0(indexedReadMethod);        }        return indexedReadMethod;    }     /**     * Sets the method that should be used to read an indexed property value.     *     * @param readMethod The new indexed read method.     */    public synchronized void setIndexedReadMethod(Method readMethod)        throws IntrospectionException {         // the indexed property type is set by the reader.        setIndexedPropertyType(findIndexedPropertyType(readMethod,                                                       getIndexedWriteMethod0()));        setIndexedReadMethod0(readMethod);    }     private void setIndexedReadMethod0(Method readMethod) {        if (readMethod == null) {            indexedReadMethodName = null;            indexedReadMethodRef = null;            return;        }        setClass0(readMethod.getDeclaringClass());         indexedReadMethodName = readMethod.getName();        this.indexedReadMethodRef = getSoftReference(readMethod);        setTransient(readMethod.getAnnotation(Transient.class));    }      /**     * Gets the method that should be used to write an indexed property value.     *     * @return The method that should be used to write an indexed     * property value.     * May return null if the property isn't indexed or is read-only.     */    public synchronized Method getIndexedWriteMethod() {        Method indexedWriteMethod = getIndexedWriteMethod0();        if (indexedWriteMethod == null) {            Class cls = getClass0();            if (cls == null ||                (indexedWriteMethodName == null && indexedWriteMethodRef == null)) {                // the Indexed writeMethod was explicitly set to null.                return null;            }             // We need the indexed type to ensure that we get the correct method.            // Cannot use the getIndexedPropertyType method since that could            // result in an infinite loop.            Class type = getIndexedPropertyType0();            if (type == null) {                try {                    type = findIndexedPropertyType(getIndexedReadMethod(), null);                    setIndexedPropertyType(type);                } catch (IntrospectionException ex) {                    // Set iprop type to be the classic type                    Class propType = getPropertyType();                    if (propType.isArray()) {                        type = propType.getComponentType();                    }                }            }             if (indexedWriteMethodName == null) {                indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName();            }             Class[] args = (type == null) ? null : new Class[] { int.class, type };            indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, 2, args);            if (indexedWriteMethod != null) {                if (!indexedWriteMethod.getReturnType().equals(void.class)) {                    indexedWriteMethod = null;                }            }            setIndexedWriteMethod0(indexedWriteMethod);        }        return indexedWriteMethod;    }     /**     * Sets the method that should be used to write an indexed property value.     *     * @param writeMethod The new indexed write method.     */    public synchronized void setIndexedWriteMethod(Method writeMethod)        throws IntrospectionException {         // If the indexed property type has not been set, then set it.        Class type = findIndexedPropertyType(getIndexedReadMethod(),                                             writeMethod);        setIndexedPropertyType(type);        setIndexedWriteMethod0(writeMethod);    }     private void setIndexedWriteMethod0(Method writeMethod) {        if (writeMethod == null) {            indexedWriteMethodName = null;            indexedWriteMethodRef = null;            return;        }        setClass0(writeMethod.getDeclaringClass());         indexedWriteMethodName = writeMethod.getName();        this.indexedWriteMethodRef = getSoftReference(writeMethod);        setTransient(writeMethod.getAnnotation(Transient.class));    }     /**     * Returns the Java type info for the indexed property.     * Note that the {@code Class} object may describe     * primitive Java types such as {@code int}.     * This type is returned by the indexed read method     * or is used as the parameter type of the indexed write method.     *     * @return the {@code Class} object that represents the Java type info,     *         or {@code null} if the type cannot be determined     */    public synchronized Class<?> getIndexedPropertyType() {        Class type = getIndexedPropertyType0();        if (type == null) {            try {                type = findIndexedPropertyType(getIndexedReadMethod(),                                               getIndexedWriteMethod());                setIndexedPropertyType(type);            } catch (IntrospectionException ex) {                // fall            }        }        return type;    }     // Private methods which set get/set the Reference objects     private void setIndexedPropertyType(Class type) {        this.indexedPropertyTypeRef = getWeakReference(type);    }     private Class getIndexedPropertyType0() {        return (this.indexedPropertyTypeRef != null)                ? this.indexedPropertyTypeRef.get()                : null;    }     private Method getIndexedReadMethod0() {        return (this.indexedReadMethodRef != null)                ? this.indexedReadMethodRef.get()                : null;    }     private Method getIndexedWriteMethod0() {        return (this.indexedWriteMethodRef != null)                ? this.indexedWriteMethodRef.get()                : null;    }     private Class findIndexedPropertyType(Method indexedReadMethod,                                          Method indexedWriteMethod)        throws IntrospectionException {        Class indexedPropertyType = null;         if (indexedReadMethod != null) {            Class params[] = getParameterTypes(getClass0(), indexedReadMethod);            if (params.length != 1) {                throw new IntrospectionException("bad indexed read method arg count");            }            if (params[0] != Integer.TYPE) {                throw new IntrospectionException("non int index to indexed read method");            }            indexedPropertyType = getReturnType(getClass0(), indexedReadMethod);            if (indexedPropertyType == Void.TYPE) {                throw new IntrospectionException("indexed read method returns void");            }        }        if (indexedWriteMethod != null) {            Class params[] = getParameterTypes(getClass0(), indexedWriteMethod);            if (params.length != 2) {                throw new IntrospectionException("bad indexed write method arg count");            }            if (params[0] != Integer.TYPE) {                throw new IntrospectionException("non int index to indexed write method");            }            if (indexedPropertyType != null && indexedPropertyType != params[1]) {                throw new IntrospectionException(                                                 "type mismatch between indexed read and indexed write methods: "                                                 + getName());            }            indexedPropertyType = params[1];        }        Class propertyType = getPropertyType();        if (propertyType != null && (!propertyType.isArray() ||                                     propertyType.getComponentType() != indexedPropertyType)) {            throw new IntrospectionException("type mismatch between indexed and non-indexed methods: "                                             + getName());        }        return indexedPropertyType;    }     /**     * Compares this <code>PropertyDescriptor</code> against the specified object.     * Returns true if the objects are the same. Two <code>PropertyDescriptor</code>s     * are the same if the read, write, property types, property editor and     * flags  are equivalent.     *     * @since 1.4     */    public boolean equals(Object obj) {        // Note: This would be identical to PropertyDescriptor but they don't        // share the same fields.        if (this == obj) {            return true;        }         if (obj != null && obj instanceof IndexedPropertyDescriptor) {            IndexedPropertyDescriptor other = (IndexedPropertyDescriptor)obj;            Method otherIndexedReadMethod = other.getIndexedReadMethod();            Method otherIndexedWriteMethod = other.getIndexedWriteMethod();             if (!compareMethods(getIndexedReadMethod(), otherIndexedReadMethod)) {                return false;            }             if (!compareMethods(getIndexedWriteMethod(), otherIndexedWriteMethod)) {                return false;            }             if (getIndexedPropertyType() != other.getIndexedPropertyType()) {                return false;            }            return super.equals(obj);        }        return false;    }     /**     * Package-private constructor.     * Merge two property descriptors.  Where they conflict, give the     * second argument (y) priority over the first argumnnt (x).     *     * @param x  The first (lower priority) PropertyDescriptor     * @param y  The second (higher priority) PropertyDescriptor     */     IndexedPropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y) {        super(x,y);        if (x instanceof IndexedPropertyDescriptor) {            IndexedPropertyDescriptor ix = (IndexedPropertyDescriptor)x;            try {                Method xr = ix.getIndexedReadMethod();                if (xr != null) {                    setIndexedReadMethod(xr);                }                 Method xw = ix.getIndexedWriteMethod();                if (xw != null) {                    setIndexedWriteMethod(xw);                }            } catch (IntrospectionException ex) {                // Should not happen                throw new AssertionError(ex);            }        }        if (y instanceof IndexedPropertyDescriptor) {            IndexedPropertyDescriptor iy = (IndexedPropertyDescriptor)y;            try {                Method yr = iy.getIndexedReadMethod();                if (yr != null && yr.getDeclaringClass() == getClass0()) {                    setIndexedReadMethod(yr);                }                 Method yw = iy.getIndexedWriteMethod();                if (yw != null && yw.getDeclaringClass() == getClass0()) {                    setIndexedWriteMethod(yw);                }            } catch (IntrospectionException ex) {                // Should not happen                throw new AssertionError(ex);            }        }    }     /*     * Package-private dup constructor     * This must isolate the new object from any changes to the old object.     */    IndexedPropertyDescriptor(IndexedPropertyDescriptor old) {        super(old);        indexedReadMethodRef = old.indexedReadMethodRef;        indexedWriteMethodRef = old.indexedWriteMethodRef;        indexedPropertyTypeRef = old.indexedPropertyTypeRef;        indexedWriteMethodName = old.indexedWriteMethodName;        indexedReadMethodName = old.indexedReadMethodName;    }     /**     * Returns a hash code value for the object.     * See {@link java.lang.Object#hashCode} for a complete description.     *

Lines 1–500 of 523.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t