in src/main/java/groovy/lang/MetaClassImpl.java [2674:2819]
public void setProperty(final Class sender, final Object object, final String name, Object newValue, final boolean useSuper, final boolean fromInsideClass) {
//----------------------------------------------------------------------
// handling of static
//----------------------------------------------------------------------
boolean isStatic = (theClass != Class.class && object instanceof Class);
if (isStatic && object != theClass) {
MetaClass mc = registry.getMetaClass((Class<?>) object);
mc.getProperty(sender, object, name, useSuper, fromInsideClass);
return;
}
checkInitalised();
//----------------------------------------------------------------------
// Unwrap wrapped values for now - the new MOP will handle them properly
//----------------------------------------------------------------------
if (newValue instanceof Wrapper) newValue = ((Wrapper) newValue).unwrap();
MetaMethod method = null;
Object[] arguments = null;
//----------------------------------------------------------------------
// setter
//----------------------------------------------------------------------
MetaProperty mp = getMetaProperty(sender, name, useSuper, isStatic);
MetaProperty field = null;
if (mp != null) {
if (mp instanceof MetaBeanProperty) {
MetaBeanProperty mbp = (MetaBeanProperty) mp;
method = mbp.getSetter();
MetaProperty f = mbp.getField();
if (method != null || (f != null && !f.isFinal())) {
arguments = new Object[]{newValue};
field = f;
}
} else {
field = mp;
}
}
// check for a category method named like a setter
if (!useSuper && !isStatic && !name.isEmpty() && GroovyCategorySupport.hasCategoryInCurrentThread()) {
var setterName = GroovyCategorySupport.getPropertyCategorySetterName(name);
if (setterName != null) {
MetaMethod categoryMethod = getCategoryMethodSetter(theClass, setterName, false);
if (categoryMethod != null) {
method = categoryMethod;
arguments = new Object[]{newValue};
}
}
}
//----------------------------------------------------------------------
// listener method
//----------------------------------------------------------------------
boolean ambiguousListener = false;
if (method == null) {
method = listeners.get(name);
ambiguousListener = (method == AMBIGUOUS_LISTENER_METHOD);
if (method != null && !ambiguousListener && newValue instanceof Closure) {
// bean.name = { -> } is short for bean.addSomeListener({ -> });
// where "name" derives from the SomeListener interface's method
var listener = method.getParameterTypes()[0].getTheClass();
Object proxy = Proxy.newProxyInstance(
listener.getClassLoader(),
new Class[]{listener},
new ConvertedClosure((Closure<?>) newValue, name));
arguments = new Object[]{proxy};
newValue = proxy;
} else {
method = null;
}
}
//----------------------------------------------------------------------
// field
//----------------------------------------------------------------------
if (method == null && field != null
&& (!isMap || isStatic // GROOVY-8065
|| field.isPublic())) { // GROOVY-11367
if (!field.isFinal()) {
field.setProperty(object, newValue);
return;
} else {
throw new ReadOnlyPropertyException(name, theClass); // GROOVY-5985
}
}
//----------------------------------------------------------------------
// generic set method
//----------------------------------------------------------------------
// check for a generic get method provided through a category
if (method == null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
method = getCategoryMethodSetter(theClass, "set", true);
if (method != null) arguments = new Object[]{name, newValue};
}
if (method == null && genericSetMethod != null && (genericSetMethod.isStatic() || !isStatic)) {
arguments = new Object[]{name, newValue};
method = genericSetMethod;
}
//----------------------------------------------------------------------
// java.util.Map put method before non-public method -- see GROOVY-11367
//----------------------------------------------------------------------
if (isMap && !isStatic && !(method != null && method.isPublic())
&& (mp == null || !mp.isPublic() || isSpecialProperty(name))) {
((Map) object).put(name, newValue);
return;
}
//----------------------------------------------------------------------
// executing the method
//----------------------------------------------------------------------
if (method != null) {
if (arguments.length == 1) {
newValue = DefaultTypeTransformation.castToType(
newValue,
method.getParameterTypes()[0].getTheClass());
arguments[0] = newValue;
} else {
newValue = DefaultTypeTransformation.castToType(
newValue,
method.getParameterTypes()[1].getTheClass());
arguments[1] = newValue;
}
VM_PLUGIN.transformMetaMethod(this, method).doMethodInvoke(object, arguments);
return;
}
//----------------------------------------------------------------------
// missing property protocol
//----------------------------------------------------------------------
if (ambiguousListener) {
throw new GroovyRuntimeException("There are multiple listeners for the property " + name + ". Please do not use the bean short form to access this listener.");
}
if (mp != null) {
throw new ReadOnlyPropertyException(name, theClass);
}
if (object instanceof Class && !"metaClass".equals(name)) {
invokeStaticMissingProperty(object, name, newValue, false);
} else {
invokeMissingProperty(object, name, newValue, false);
}
}