Search in sources :

Example 1 with Wrapper

use of org.codehaus.groovy.runtime.wrappers.Wrapper in project groovy-core by groovy.

the class MetaClassImpl method setProperty.

/**
 * <p>Retrieves a property on the given receiver for the specified arguments. The sender is the class that is requesting the property from the object.
 * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
 *
 * <p>The useSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
 * to the super class if necessary
 *
 * @param sender The java.lang.Class instance that is mutating the property
 * @param object The Object which the property is being set on
 * @param name The name of the property
 * @param newValue The new value of the property to set
 * @param useSuper Whether the call is to a super class property
 * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class.
 */
public void setProperty(Class sender, Object object, String name, Object newValue, boolean useSuper, boolean fromInsideClass) {
    checkInitalised();
    // ----------------------------------------------------------------------
    // 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;
    }
    // ----------------------------------------------------------------------
    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 && !Modifier.isFinal(f.getModifiers()))) {
                arguments = new Object[] { newValue };
                field = f;
            }
        } else {
            field = mp;
        }
    }
    // check for a category method named like a setter
    if (!useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread() && name.length() > 0) {
        String getterName = GroovyCategorySupport.getPropertyCategorySetterName(name);
        if (getterName != null) {
            MetaMethod categoryMethod = getCategoryMethodSetter(sender, getterName, false);
            if (categoryMethod != null) {
                method = categoryMethod;
                arguments = new Object[] { newValue };
            }
        }
    }
    // ----------------------------------------------------------------------
    // listener method
    // ----------------------------------------------------------------------
    boolean ambiguousListener = false;
    if (method == null) {
        method = (MetaMethod) listeners.get(name);
        ambiguousListener = method == AMBIGUOUS_LISTENER_METHOD;
        if (method != null && !ambiguousListener && newValue instanceof Closure) {
            // let's create a dynamic proxy
            Object proxy = Proxy.newProxyInstance(theClass.getClassLoader(), new Class[] { method.getParameterTypes()[0].getTheClass() }, new ConvertedClosure((Closure) newValue, name));
            arguments = new Object[] { proxy };
            newValue = proxy;
        } else {
            method = null;
        }
    }
    // ----------------------------------------------------------------------
    if (method == null && field != null) {
        if (Modifier.isFinal(field.getModifiers())) {
            throw new ReadOnlyPropertyException(name, theClass);
        }
        if (!(this.isMap && isPrivateOrPkgPrivate(field.getModifiers()))) {
            field.setProperty(object, newValue);
            return;
        }
    }
    // check for a generic get method provided through a category
    if (method == null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
        method = getCategoryMethodSetter(sender, "set", true);
        if (method != null)
            arguments = new Object[] { name, newValue };
    }
    // if it is not static and we do no static access
    if (method == null && genericSetMethod != null && !(!genericSetMethod.isStatic() && isStatic)) {
        arguments = new Object[] { name, newValue };
        method = genericSetMethod;
    }
    // ----------------------------------------------------------------------
    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;
        }
        method.doMethodInvoke(object, arguments);
        return;
    }
    // ----------------------------------------------------------------------
    if (!isStatic && this.isMap) {
        ((Map) object).put(name, newValue);
        return;
    }
    // ----------------------------------------------------------------------
    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);
    }
    invokeMissingProperty(object, name, newValue, false);
}
Also used : NewInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod) NewMetaMethod(org.codehaus.groovy.runtime.metaclass.NewMetaMethod) MixinInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod) NewStaticMetaMethod(org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod) GeneratedMetaMethod(org.codehaus.groovy.reflection.GeneratedMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) TransformMetaMethod(org.codehaus.groovy.runtime.metaclass.TransformMetaMethod) Wrapper(org.codehaus.groovy.runtime.wrappers.Wrapper) ConvertedClosure(org.codehaus.groovy.runtime.ConvertedClosure) MethodClosure(org.codehaus.groovy.runtime.MethodClosure) GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure) CurriedClosure(org.codehaus.groovy.runtime.CurriedClosure) ConvertedClosure(org.codehaus.groovy.runtime.ConvertedClosure) CachedClass(org.codehaus.groovy.reflection.CachedClass) GetMethodMetaProperty(org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty) GetBeanMethodMetaProperty(org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty) SingleKeyHashMap(org.codehaus.groovy.util.SingleKeyHashMap) ComplexKeyHashMap(org.codehaus.groovy.util.ComplexKeyHashMap)

Example 2 with Wrapper

use of org.codehaus.groovy.runtime.wrappers.Wrapper in project groovy by apache.

the class MetaClassImpl method setProperty.

/**
 * <p>Retrieves a property on the given receiver for the specified arguments. The sender is the class that is requesting the property from the object.
 * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
 *
 * <p>The useSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
 * to the super class if necessary
 *
 * @param sender          The java.lang.Class instance that is mutating the property
 * @param object          The Object which the property is being set on
 * @param name            The name of the property
 * @param newValue        The new value of the property to set
 * @param useSuper        Whether the call is to a super class property
 * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class.
 */
@Override
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();
    // ----------------------------------------------------------------------
    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 && !Modifier.isFinal(f.getModifiers()))) {
                arguments = new Object[] { newValue };
                field = f;
            }
        } else {
            field = mp;
        }
    }
    // check for a category method named like a setter
    if (!useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread() && name.length() > 0) {
        String getterName = GroovyCategorySupport.getPropertyCategorySetterName(name);
        if (getterName != null) {
            MetaMethod categoryMethod = getCategoryMethodSetter(sender, getterName, 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) {
            // let's create a dynamic proxy
            Object proxy = Proxy.newProxyInstance(theClass.getClassLoader(), new Class[] { method.getParameterTypes()[0].getTheClass() }, new ConvertedClosure((Closure) newValue, name));
            arguments = new Object[] { proxy };
            newValue = proxy;
        } else {
            method = null;
        }
    }
    // ----------------------------------------------------------------------
    if (method == null && field != null) {
        boolean mapInstance = (isMap && !isStatic);
        int modifiers = field.getModifiers();
        if (Modifier.isFinal(modifiers)) {
            if (mapInstance) {
                // GROOVY-8065
                ((Map) object).put(name, newValue);
                return;
            }
            // GROOVY-5985
            throw new ReadOnlyPropertyException(name, theClass);
        }
        if (!mapInstance || Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) {
            field.setProperty(object, newValue);
            return;
        }
    }
    // check for a generic get method provided through a category
    if (method == null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
        method = getCategoryMethodSetter(sender, "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;
    }
    // ----------------------------------------------------------------------
    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;
    }
    // ------------------------------------------------------------------
    if (isMap && !isStatic) {
        ((Map) object).put(name, newValue);
        return;
    }
    // ----------------------------------------------------------------------
    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 ((isStatic || object instanceof Class) && !"metaClass".equals(name)) {
        invokeStaticMissingProperty(object, name, newValue, false);
    } else {
        invokeMissingProperty(object, name, newValue, false);
    }
}
Also used : NewInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod) NewMetaMethod(org.codehaus.groovy.runtime.metaclass.NewMetaMethod) GeneratedMetaMethod(org.codehaus.groovy.reflection.GeneratedMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) MixinInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod) NewStaticMetaMethod(org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod) TransformMetaMethod(org.codehaus.groovy.runtime.metaclass.TransformMetaMethod) Wrapper(org.codehaus.groovy.runtime.wrappers.Wrapper) ConvertedClosure(org.codehaus.groovy.runtime.ConvertedClosure) CurriedClosure(org.codehaus.groovy.runtime.CurriedClosure) ConvertedClosure(org.codehaus.groovy.runtime.ConvertedClosure) MethodClosure(org.codehaus.groovy.runtime.MethodClosure) GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure) CachedClass(org.codehaus.groovy.reflection.CachedClass) GetBeanMethodMetaProperty(org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty) GetMethodMetaProperty(org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty) Map(java.util.Map) SingleKeyHashMap(org.codehaus.groovy.util.SingleKeyHashMap) LinkedHashMap(java.util.LinkedHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) ComplexKeyHashMap(org.codehaus.groovy.util.ComplexKeyHashMap)

Aggregations

CachedClass (org.codehaus.groovy.reflection.CachedClass)2 GeneratedMetaMethod (org.codehaus.groovy.reflection.GeneratedMetaMethod)2 ConvertedClosure (org.codehaus.groovy.runtime.ConvertedClosure)2 CurriedClosure (org.codehaus.groovy.runtime.CurriedClosure)2 GeneratedClosure (org.codehaus.groovy.runtime.GeneratedClosure)2 MethodClosure (org.codehaus.groovy.runtime.MethodClosure)2 ClosureMetaMethod (org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod)2 GetBeanMethodMetaProperty (org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty)2 GetMethodMetaProperty (org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty)2 MixinInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod)2 NewInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod)2 NewMetaMethod (org.codehaus.groovy.runtime.metaclass.NewMetaMethod)2 NewStaticMetaMethod (org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod)2 TransformMetaMethod (org.codehaus.groovy.runtime.metaclass.TransformMetaMethod)2 Wrapper (org.codehaus.groovy.runtime.wrappers.Wrapper)2 ComplexKeyHashMap (org.codehaus.groovy.util.ComplexKeyHashMap)2 SingleKeyHashMap (org.codehaus.groovy.util.SingleKeyHashMap)2 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1