0N/A/*
5879N/A * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/Apackage com.sun.beans.decoder;
0N/A
0N/Aimport com.sun.beans.finder.MethodFinder;
0N/A
0N/Aimport java.beans.IndexedPropertyDescriptor;
0N/Aimport java.beans.IntrospectionException;
0N/Aimport java.beans.Introspector;
0N/Aimport java.beans.PropertyDescriptor;
0N/A
0N/Aimport java.lang.reflect.Array;
0N/Aimport java.lang.reflect.InvocationTargetException;
1966N/Aimport java.lang.reflect.Method;
1966N/A
1966N/Aimport sun.reflect.misc.MethodUtil;
1966N/A
1966N/A/**
0N/A * This class is intended to handle <property> element.
0N/A * This element simplifies access to the properties.
0N/A * If the {@code index} attribute is specified
0N/A * this element uses additional {@code int} parameter.
0N/A * If the {@code name} attribute is not specified
0N/A * this element uses method "get" as getter
1966N/A * and method "set" as setter.
1966N/A * This element defines getter if it contains no argument.
1696N/A * It returns the value of the property in this case.
0N/A * For example:<pre>
1045N/A * &lt;property name="object" index="10"/&gt;</pre>
0N/A * is shortcut to<pre>
0N/A * &lt;method name="getObject"&gt;
0N/A * &lt;int&gt;10&lt;/int&gt;
0N/A * &lt;/method&gt;</pre>
6323N/A * which is equivalent to {@code getObject(10)} in Java code.
0N/A * This element defines setter if it contains one argument.
1045N/A * It does not return the value of the property in this case.
1045N/A * For example:<pre>
0N/A * &lt;property&gt;&lt;int&gt;0&lt;/int&gt;&lt;/property&gt;</pre>
216N/A * is shortcut to<pre>
0N/A * &lt;method name="set"&gt;
1696N/A * &lt;int&gt;0&lt;/int&gt;
1696N/A * &lt;/method&gt;</pre>
1696N/A * which is equivalent to {@code set(0)} in Java code.
1696N/A * <p>The following atributes are supported:
1696N/A * <dl>
0N/A * <dt>name
0N/A * <dd>the property name
0N/A * <dt>index
0N/A * <dd>the property index
0N/A * <dt>id
0N/A * <dd>the identifier of the variable that is intended to store the result
0N/A * </dl>
0N/A *
0N/A * @since 1.7
0N/A *
0N/A * @author Sergey A. Malenkov
0N/A */
0N/Afinal class PropertyElementHandler extends AccessorElementHandler {
0N/A static final String GETTER = "get"; // NON-NLS: the getter prefix
0N/A static final String SETTER = "set"; // NON-NLS: the setter prefix
0N/A
0N/A private Integer index;
0N/A
0N/A /**
0N/A * Parses attributes of the element.
0N/A * The following atributes are supported:
0N/A * <dl>
0N/A * <dt>name
0N/A * <dd>the property name
0N/A * <dt>index
0N/A * <dd>the property index
0N/A * <dt>id
0N/A * <dd>the identifier of the variable that is intended to store the result
1966N/A * </dl>
1966N/A *
0N/A * @param name the attribute name
0N/A * @param value the attribute value
0N/A */
0N/A @Override
0N/A public void addAttribute(String name, String value) {
0N/A if (name.equals("index")) { // NON-NLS: the attribute name
0N/A this.index = Integer.valueOf(value);
1971N/A } else {
1971N/A super.addAttribute(name, value);
1971N/A }
1971N/A }
1971N/A
1971N/A /**
1971N/A * Tests whether the value of this element can be used
1971N/A * as an argument of the element that contained in this one.
1971N/A *
1971N/A * @return {@code true} if the value of this element should be used
1971N/A * as an argument of the element that contained in this one,
1971N/A * {@code false} otherwise
0N/A */
0N/A @Override
0N/A protected boolean isArgument() {
0N/A return false; // non-static accessor cannot be used an argument
0N/A }
0N/A
0N/A /**
0N/A * Returns the value of the property with specified {@code name}.
0N/A *
0N/A * @param name the name of the property
0N/A * @return the value of the specified property
0N/A */
0N/A @Override
0N/A protected Object getValue(String name) {
0N/A try {
0N/A return getPropertyValue(getContextBean(), name, this.index);
0N/A }
0N/A catch (Exception exception) {
0N/A getOwner().handleException(exception);
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A /**
0N/A * Sets the new value for the property with specified {@code name}.
0N/A *
0N/A * @param name the name of the property
0N/A * @param value the new value for the specified property
0N/A */
0N/A @Override
562N/A protected void setValue(String name, Object value) {
1971N/A try {
0N/A setPropertyValue(getContextBean(), name, this.index, value);
0N/A }
0N/A catch (Exception exception) {
216N/A getOwner().handleException(exception);
0N/A }
1066N/A }
1066N/A
1066N/A /**
1066N/A * Performs the search of the getter for the property
1066N/A * with specified {@code name} in specified class
1066N/A * and returns value of the property.
1066N/A *
0N/A * @param bean the context bean that contains property
0N/A * @param name the name of the property
0N/A * @param index the index of the indexed property
0N/A * @return the value of the property
0N/A * @throws IllegalAccessException if the property is not accesible
1157N/A * @throws IntrospectionException if the bean introspection is failed
1157N/A * @throws InvocationTargetException if the getter cannot be invoked
1157N/A * @throws NoSuchMethodException if the getter is not found
1157N/A */
1157N/A private static Object getPropertyValue(Object bean, String name, Integer index) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException {
1157N/A Class<?> type = bean.getClass();
1157N/A if (index == null) {
0N/A return MethodUtil.invoke(findGetter(type, name), bean, new Object[] {});
0N/A } else if (type.isArray() && (name == null)) {
0N/A return Array.get(bean, index);
0N/A } else {
93N/A return MethodUtil.invoke(findGetter(type, name, int.class), bean, new Object[] {index});
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Performs the search of the setter for the property
0N/A * with specified {@code name} in specified class
0N/A * and updates value of the property.
0N/A *
0N/A * @param bean the context bean that contains property
0N/A * @param name the name of the property
0N/A * @param index the index of the indexed property
0N/A * @param value the new value for the property
0N/A * @throws IllegalAccessException if the property is not accesible
0N/A * @throws IntrospectionException if the bean introspection is failed
0N/A * @throws InvocationTargetException if the setter cannot be invoked
0N/A * @throws NoSuchMethodException if the setter is not found
0N/A */
0N/A private static void setPropertyValue(Object bean, String name, Integer index, Object value) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException {
0N/A Class<?> type = bean.getClass();
0N/A Class<?> param = (value != null)
0N/A ? value.getClass()
0N/A : null;
0N/A
0N/A if (index == null) {
0N/A MethodUtil.invoke(findSetter(type, name, param), bean, new Object[] {value});
0N/A } else if (type.isArray() && (name == null)) {
0N/A Array.set(bean, index, value);
0N/A } else {
0N/A MethodUtil.invoke(findSetter(type, name, int.class, param), bean, new Object[] {index, value});
0N/A }
0N/A }
0N/A
4514N/A /**
4514N/A * Performs the search of the getter for the property
4514N/A * with specified {@code name} in specified class.
0N/A *
0N/A * @param type the class that contains method
0N/A * @param name the name of the property
0N/A * @param args the method arguments
0N/A * @return method object that represents found getter
0N/A * @throws IntrospectionException if the bean introspection is failed
4514N/A * @throws NoSuchMethodException if method is not found
4514N/A */
4514N/A private static Method findGetter(Class<?> type, String name, Class<?>...args) throws IntrospectionException, NoSuchMethodException {
4514N/A if (name == null) {
0N/A return MethodFinder.findInstanceMethod(type, GETTER, args);
0N/A }
0N/A PropertyDescriptor pd = getProperty(type, name);
0N/A if (args.length == 0) {
0N/A Method method = pd.getReadMethod();
1696N/A if (method != null) {
0N/A return method;
0N/A }
0N/A } else if (pd instanceof IndexedPropertyDescriptor) {
0N/A IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
0N/A Method method = ipd.getIndexedReadMethod();
0N/A if (method != null) {
0N/A return method;
0N/A }
0N/A }
0N/A throw new IntrospectionException("Could not find getter for the " + name + " property");
0N/A }
0N/A
1696N/A /**
0N/A * Performs the search of the setter for the property
0N/A * with specified {@code name} in specified class.
0N/A *
0N/A * @param type the class that contains method
0N/A * @param name the name of the property
216N/A * @param args the method arguments
0N/A * @return method object that represents found setter
0N/A * @throws IntrospectionException if the bean introspection is failed
0N/A * @throws NoSuchMethodException if method is not found
0N/A */
0N/A private static Method findSetter(Class<?> type, String name, Class<?>...args) throws IntrospectionException, NoSuchMethodException {
0N/A if (name == null) {
0N/A return MethodFinder.findInstanceMethod(type, SETTER, args);
0N/A }
0N/A PropertyDescriptor pd = getProperty(type, name);
4618N/A if (args.length == 1) {
4618N/A Method method = pd.getWriteMethod();
4618N/A if (method != null) {
4618N/A return method;
4618N/A }
4618N/A } else if (pd instanceof IndexedPropertyDescriptor) {
4618N/A IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
4618N/A Method method = ipd.getIndexedWriteMethod();
4618N/A if (method != null) {
4618N/A return method;
4618N/A }
4618N/A }
4618N/A throw new IntrospectionException("Could not find setter for the " + name + " property");
4618N/A }
0N/A
0N/A /**
0N/A * Performs the search of the descriptor for the property
0N/A * with specified {@code name} in specified class.
1976N/A *
1066N/A * @param type the class to introspect
0N/A * @param name the property name
0N/A * @return descriptor for the named property
0N/A * @throws IntrospectionException if property descriptor is not found
0N/A */
0N/A private static PropertyDescriptor getProperty(Class<?> type, String name) throws IntrospectionException {
0N/A for (PropertyDescriptor pd : Introspector.getBeanInfo(type).getPropertyDescriptors()) {
1045N/A if (name.equals(pd.getName())) {
1045N/A return pd;
1045N/A }
1045N/A }
0N/A throw new IntrospectionException("Could not find the " + name + " property descriptor");
0N/A }
0N/A}
0N/A