/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.internal.util.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Locale;
/**
* This utility class will call the setter of the property to inject a new value.
*/
public class BeanPropertySetter {
private static final String SET_PREFIX = "set";
private final Object target;
private boolean reportNoSetterFound;
private final Field field;
/**
* New BeanPropertySetter
* @param target The target on which the setter must be invoked
* @param propertyField The field that should be accessed with the setter
* @param reportNoSetterFound Allow the set method to raise an Exception if the setter cannot be found
*/
public BeanPropertySetter(final Object target, final Field propertyField, boolean reportNoSetterFound) {
this.field = propertyField;
this.target = target;
this.reportNoSetterFound = reportNoSetterFound;
}
/**
* New BeanPropertySetter that don't report failure
* @param target The target on which the setter must be invoked
* @param propertyField The propertyField that must be accessed through a setter
*/
public BeanPropertySetter(final Object target, final Field propertyField) {
this(target, propertyField, false);
}
/**
* Set the value to the property represented by this {@link BeanPropertySetter}
* @param value the new value to pass to the property setter
* @return true
if the value has been injected, false
otherwise
* @throws RuntimeException Can be thrown if the setter threw an exception, if the setter is not accessible
* or, if reportNoSetterFound
and setter could not be found.
*/
public boolean set(final Object value) {
AccessibilityChanger changer = new AccessibilityChanger();
Method writeMethod = null;
try {
writeMethod = target.getClass().getMethod(setterName(field.getName()), field.getType());
changer.enableAccess(writeMethod);
writeMethod.invoke(target, value);
return true;
} catch (InvocationTargetException e) {
throw new RuntimeException("Setter '" + writeMethod + "' of '" + target + "' with value '" + value + "' threw exception : '" + e.getTargetException() + "'", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Access not authorized on field '" + field + "' of object '" + target + "' with value: '" + value + "'", e);
} catch (NoSuchMethodException e) {
reportNoSetterFound();
} finally {
if(writeMethod != null) {
changer.safelyDisableAccess(writeMethod);
}
}
reportNoSetterFound();
return false;
}
/**
* Retrieve the setter name from the field name.
*
*
Implementation is based on the code of {@link java.beans.Introspector}.
* * @param fieldName the Field name * @return Setter name. */ private String setterName(String fieldName) { return new StringBuilder(SET_PREFIX) .append(fieldName.substring(0, 1).toUpperCase(Locale.ENGLISH)) .append(fieldName.substring(1)) .toString(); } private void reportNoSetterFound() { if(reportNoSetterFound) { throw new RuntimeException("Problems setting value on object: [" + target + "] for property : [" + field.getName() + "], setter not found"); } } }