Path: blob/master/src/java.desktop/share/classes/com/sun/beans/decoder/PropertyElementHandler.java
41171 views
/*1* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package com.sun.beans.decoder;2526import com.sun.beans.finder.MethodFinder;2728import java.beans.IndexedPropertyDescriptor;29import java.beans.IntrospectionException;30import java.beans.Introspector;31import java.beans.PropertyDescriptor;3233import java.lang.reflect.Array;34import java.lang.reflect.InvocationTargetException;35import java.lang.reflect.Method;3637import sun.reflect.misc.MethodUtil;3839/**40* This class is intended to handle <property> element.41* This element simplifies access to the properties.42* If the {@code index} attribute is specified43* this element uses additional {@code int} parameter.44* If the {@code name} attribute is not specified45* this element uses method "get" as getter46* and method "set" as setter.47* This element defines getter if it contains no argument.48* It returns the value of the property in this case.49* For example:<pre>50* <property name="object" index="10"/></pre>51* is shortcut to<pre>52* <method name="getObject">53* <int>10</int>54* </method></pre>55* which is equivalent to {@code getObject(10)} in Java code.56* This element defines setter if it contains one argument.57* It does not return the value of the property in this case.58* For example:<pre>59* <property><int>0</int></property></pre>60* is shortcut to<pre>61* <method name="set">62* <int>0</int>63* </method></pre>64* which is equivalent to {@code set(0)} in Java code.65* <p>The following attributes are supported:66* <dl>67* <dt>name68* <dd>the property name69* <dt>index70* <dd>the property index71* <dt>id72* <dd>the identifier of the variable that is intended to store the result73* </dl>74*75* @since 1.776*77* @author Sergey A. Malenkov78*/79final class PropertyElementHandler extends AccessorElementHandler {80static final String GETTER = "get"; // NON-NLS: the getter prefix81static final String SETTER = "set"; // NON-NLS: the setter prefix8283private Integer index;8485/**86* Parses attributes of the element.87* The following attributes are supported:88* <dl>89* <dt>name90* <dd>the property name91* <dt>index92* <dd>the property index93* <dt>id94* <dd>the identifier of the variable that is intended to store the result95* </dl>96*97* @param name the attribute name98* @param value the attribute value99*/100@Override101public void addAttribute(String name, String value) {102if (name.equals("index")) { // NON-NLS: the attribute name103this.index = Integer.valueOf(value);104} else {105super.addAttribute(name, value);106}107}108109/**110* Tests whether the value of this element can be used111* as an argument of the element that contained in this one.112*113* @return {@code true} if the value of this element should be used114* as an argument of the element that contained in this one,115* {@code false} otherwise116*/117@Override118protected boolean isArgument() {119return false; // non-static accessor cannot be used an argument120}121122/**123* Returns the value of the property with specified {@code name}.124*125* @param name the name of the property126* @return the value of the specified property127*/128@Override129protected Object getValue(String name) {130try {131return getPropertyValue(getContextBean(), name, this.index);132}133catch (Exception exception) {134getOwner().handleException(exception);135}136return null;137}138139/**140* Sets the new value for the property with specified {@code name}.141*142* @param name the name of the property143* @param value the new value for the specified property144*/145@Override146protected void setValue(String name, Object value) {147try {148setPropertyValue(getContextBean(), name, this.index, value);149}150catch (Exception exception) {151getOwner().handleException(exception);152}153}154155/**156* Performs the search of the getter for the property157* with specified {@code name} in specified class158* and returns value of the property.159*160* @param bean the context bean that contains property161* @param name the name of the property162* @param index the index of the indexed property163* @return the value of the property164* @throws IllegalAccessException if the property is not accesible165* @throws IntrospectionException if the bean introspection is failed166* @throws InvocationTargetException if the getter cannot be invoked167* @throws NoSuchMethodException if the getter is not found168*/169private static Object getPropertyValue(Object bean, String name, Integer index) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException {170Class<?> type = bean.getClass();171if (index == null) {172return MethodUtil.invoke(findGetter(type, name), bean, new Object[] {});173} else if (type.isArray() && (name == null)) {174return Array.get(bean, index);175} else {176return MethodUtil.invoke(findGetter(type, name, int.class), bean, new Object[] {index});177}178}179180/**181* Performs the search of the setter for the property182* with specified {@code name} in specified class183* and updates value of the property.184*185* @param bean the context bean that contains property186* @param name the name of the property187* @param index the index of the indexed property188* @param value the new value for the property189* @throws IllegalAccessException if the property is not accesible190* @throws IntrospectionException if the bean introspection is failed191* @throws InvocationTargetException if the setter cannot be invoked192* @throws NoSuchMethodException if the setter is not found193*/194private static void setPropertyValue(Object bean, String name, Integer index, Object value) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException {195Class<?> type = bean.getClass();196Class<?> param = (value != null)197? value.getClass()198: null;199200if (index == null) {201MethodUtil.invoke(findSetter(type, name, param), bean, new Object[] {value});202} else if (type.isArray() && (name == null)) {203Array.set(bean, index, value);204} else {205MethodUtil.invoke(findSetter(type, name, int.class, param), bean, new Object[] {index, value});206}207}208209/**210* Performs the search of the getter for the property211* with specified {@code name} in specified class.212*213* @param type the class that contains method214* @param name the name of the property215* @param args the method arguments216* @return method object that represents found getter217* @throws IntrospectionException if the bean introspection is failed218* @throws NoSuchMethodException if method is not found219*/220private static Method findGetter(Class<?> type, String name, Class<?>...args) throws IntrospectionException, NoSuchMethodException {221if (name == null) {222return MethodFinder.findInstanceMethod(type, GETTER, args);223}224PropertyDescriptor pd = getProperty(type, name);225if (args.length == 0) {226Method method = pd.getReadMethod();227if (method != null) {228return method;229}230} else if (pd instanceof IndexedPropertyDescriptor) {231IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;232Method method = ipd.getIndexedReadMethod();233if (method != null) {234return method;235}236}237throw new IntrospectionException("Could not find getter for the " + name + " property");238}239240/**241* Performs the search of the setter for the property242* with specified {@code name} in specified class.243*244* @param type the class that contains method245* @param name the name of the property246* @param args the method arguments247* @return method object that represents found setter248* @throws IntrospectionException if the bean introspection is failed249* @throws NoSuchMethodException if method is not found250*/251private static Method findSetter(Class<?> type, String name, Class<?>...args) throws IntrospectionException, NoSuchMethodException {252if (name == null) {253return MethodFinder.findInstanceMethod(type, SETTER, args);254}255PropertyDescriptor pd = getProperty(type, name);256if (args.length == 1) {257Method method = pd.getWriteMethod();258if (method != null) {259return method;260}261} else if (pd instanceof IndexedPropertyDescriptor) {262IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;263Method method = ipd.getIndexedWriteMethod();264if (method != null) {265return method;266}267}268throw new IntrospectionException("Could not find setter for the " + name + " property");269}270271/**272* Performs the search of the descriptor for the property273* with specified {@code name} in specified class.274*275* @param type the class to introspect276* @param name the property name277* @return descriptor for the named property278* @throws IntrospectionException if property descriptor is not found279*/280private static PropertyDescriptor getProperty(Class<?> type, String name) throws IntrospectionException {281for (PropertyDescriptor pd : Introspector.getBeanInfo(type).getPropertyDescriptors()) {282if (name.equals(pd.getName())) {283return pd;284}285}286throw new IntrospectionException("Could not find the " + name + " property descriptor");287}288}289290291