/* Copyright 2005-2006 Tim Fennell * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.sourceforge.stripes.util.bean; import net.sourceforge.stripes.util.ReflectUtil; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * Implementation of {@link PropertyAccessor} for reading JavaBean properties from * JavaBeans. Will attempt property access first using the standard PropertyDescriptor, * but if no PropertyDescriptor is present then falls back to attempting Field access for * public fields. * * @author Tim Fennell * @since Stripes 1.4 */ public class JavaBeanPropertyAccessor implements PropertyAccessor<Object> { /** * Fetches the specified property value from the bean if it exists. * @param evaluation the current node evaluation * @param bean the bean from which to fetch the property * @return the value of the property * @throws NoSuchPropertyException if there is no property with the supplied name * @throws EvaluationException if the value cannot be retrieved for any other reason */ public Object getValue(NodeEvaluation evaluation, Object bean) throws NoSuchPropertyException, EvaluationException { String property = evaluation.getNode().getStringValue(); PropertyDescriptor pd = ReflectUtil.getPropertyDescriptor(bean.getClass(), property); try { if (pd != null) { Method m = pd.getReadMethod(); if (m != null) { m = ReflectUtil.findAccessibleMethod(m); return m.invoke(bean); } else { throw new EvaluationException("Could not read write-only property '" + property + "' on bean of type " + bean.getClass().getName()); } } else { Field field = ReflectUtil.getField(bean.getClass(), property); if (field != null) { return field.get(bean); } else { throw new NoSuchPropertyException("Bean class " + bean.getClass().getName() + " does not contain a property called '" + property + "'."); } } } catch (EvaluationException ee) { throw ee; } catch (Exception e) { throw new EvaluationException("Could not read value of property '" + property + "' on bean of type " + bean.getClass().getName() + " due to an exception.", e); } } /** * Sets the specified property value to the supplied value. * @param evaluation the current node evaluation * @param bean the bean on to which to set the property * @param value the value of the property * @throws NoSuchPropertyException if there is no property with the supplied name * @throws EvaluationException if the value cannot be set for any other reason */ public void setValue(NodeEvaluation evaluation, Object bean, Object value) { String property = evaluation.getNode().getStringValue(); PropertyDescriptor pd = ReflectUtil.getPropertyDescriptor(bean.getClass(), property); try { if (pd != null) { Method m = pd.getWriteMethod(); if (m != null) { m = ReflectUtil.findAccessibleMethod(m); m.invoke(bean, value); } else { throw new EvaluationException("Could not write read-only property '" + property + "' on bean of type " + bean.getClass().getName()); } } else { Field field = ReflectUtil.getField(bean.getClass(), property); if (field != null) { field.set(bean, value); } else { throw new NoSuchPropertyException("Bean class " + bean.getClass().getName() + " does not contain a property called '" + property + "'."); } } } catch (EvaluationException ee) { throw ee; } catch (Exception e) { throw new EvaluationException("Could not write value of property '" + property + "' on bean of type " + bean.getClass().getName() + " due to an exception.", e); } } }