blob: d84d57a3ed29088b3b95b9267e2e79f1df7476a1 [file] [log] [blame]
/*
* 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 <code>true</code> if the value has been injected, <code>false</code> otherwise
* @throws RuntimeException Can be thrown if the setter threw an exception, if the setter is not accessible
* or, if <code>reportNoSetterFound</code> 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.
*
* <p>Implementation is based on the code of {@link java.beans.Introspector}.</p>
*
* @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");
}
}
}