Search in sources :

Example 1 with ClosureMetaMethod

use of org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod in project groovy by apache.

the class MetaClassImpl method invokeMissingProperty.

/**
     * Invoke a missing property on the given object with the given arguments.
     *
     * @param instance The object the method should be invoked on.
     * @param propertyName The name of the property to invoke.
     * @param optionalValue The (optional) new value for the property
     * @param isGetter Wether the method is a getter
     *
     * @return The result of the method invocation.
     */
public Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
    Class theClass = instance instanceof Class ? (Class) instance : instance.getClass();
    CachedClass superClass = theCachedClass;
    while (superClass != null && superClass != ReflectionCache.OBJECT_CLASS) {
        final MetaBeanProperty property = findPropertyInClassHierarchy(propertyName, superClass);
        if (property != null) {
            onSuperPropertyFoundInHierarchy(property);
            if (!isGetter) {
                property.setProperty(instance, optionalValue);
                return null;
            } else {
                return property.getProperty(instance);
            }
        }
        superClass = superClass.getCachedSuperClass();
    }
    // got here to property not found, look for getProperty or setProperty overrides
    if (isGetter) {
        final Class[] getPropertyArgs = { String.class };
        final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), GET_PROPERTY_METHOD, getPropertyArgs, this);
        if (method != null && method instanceof ClosureMetaMethod) {
            onGetPropertyFoundInHierarchy(method);
            return method.invoke(instance, new Object[] { propertyName });
        }
    } else {
        final Class[] setPropertyArgs = { String.class, Object.class };
        final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), SET_PROPERTY_METHOD, setPropertyArgs, this);
        if (method != null && method instanceof ClosureMetaMethod) {
            onSetPropertyFoundInHierarchy(method);
            return method.invoke(instance, new Object[] { propertyName, optionalValue });
        }
    }
    try {
        if (!(instance instanceof Class)) {
            if (isGetter) {
                if (propertyMissingGet != null) {
                    return propertyMissingGet.invoke(instance, new Object[] { propertyName });
                }
            } else {
                if (propertyMissingSet != null) {
                    return propertyMissingSet.invoke(instance, new Object[] { propertyName, optionalValue });
                }
            }
        }
    } catch (InvokerInvocationException iie) {
        boolean shouldHandle = isGetter && propertyMissingGet != null;
        if (!shouldHandle)
            shouldHandle = !isGetter && propertyMissingSet != null;
        if (shouldHandle && iie.getCause() instanceof MissingPropertyException) {
            throw (MissingPropertyException) iie.getCause();
        }
        throw iie;
    }
    if (instance instanceof Class && theClass != Class.class) {
        final MetaProperty metaProperty = InvokerHelper.getMetaClass(Class.class).hasProperty(instance, propertyName);
        if (metaProperty != null)
            if (isGetter)
                return metaProperty.getProperty(instance);
            else {
                metaProperty.setProperty(instance, optionalValue);
                return null;
            }
    }
    throw new MissingPropertyExceptionNoStack(propertyName, theClass);
}
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) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) MissingPropertyExceptionNoStack(org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack) InvokerInvocationException(org.codehaus.groovy.runtime.InvokerInvocationException) CachedClass(org.codehaus.groovy.reflection.CachedClass) CachedClass(org.codehaus.groovy.reflection.CachedClass) GetMethodMetaProperty(org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty) GetBeanMethodMetaProperty(org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty)

Example 2 with ClosureMetaMethod

use of org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod in project groovy-core by groovy.

the class ExpandoMetaClass method addSuperMethodIfNotOverridden.

private void addSuperMethodIfNotOverridden(final MetaMethod metaMethodFromSuper) {
    performOperationOnMetaClass(new Callable() {

        public void call() {
            MetaMethod existing = null;
            try {
                existing = pickMethod(metaMethodFromSuper.getName(), metaMethodFromSuper.getNativeParameterTypes());
            } catch (GroovyRuntimeException e) {
            // ignore, this happens with overlapping method definitions
            }
            if (existing == null) {
                addMethodWithKey(metaMethodFromSuper);
            } else {
                boolean isGroovyMethod = getMetaMethods().contains(existing);
                if (isGroovyMethod) {
                    addMethodWithKey(metaMethodFromSuper);
                } else if (inheritedMetaMethods.contains(existing)) {
                    inheritedMetaMethods.remove(existing);
                    addMethodWithKey(metaMethodFromSuper);
                }
            }
        }

        private void addMethodWithKey(final MetaMethod metaMethodFromSuper) {
            inheritedMetaMethods.add(metaMethodFromSuper);
            if (metaMethodFromSuper instanceof ClosureMetaMethod) {
                ClosureMetaMethod closureMethod = (ClosureMetaMethod) metaMethodFromSuper;
                String name = metaMethodFromSuper.getName();
                final Class declaringClass = metaMethodFromSuper.getDeclaringClass().getTheClass();
                ClosureMetaMethod localMethod = ClosureMetaMethod.copy(closureMethod);
                addMetaMethod(localMethod);
                MethodKey key = new DefaultCachedMethodKey(declaringClass, name, localMethod.getParameterTypes(), false);
                checkIfGroovyObjectMethod(localMethod);
                expandoMethods.put(key, localMethod);
            }
        }
    });
}
Also used : ClosureStaticMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureStaticMetaMethod) MixinInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) OwnedMetaClass(org.codehaus.groovy.runtime.metaclass.OwnedMetaClass) MixedInMetaClass(org.codehaus.groovy.runtime.metaclass.MixedInMetaClass) CachedClass(org.codehaus.groovy.reflection.CachedClass) MixinInMetaClass(org.codehaus.groovy.reflection.MixinInMetaClass) DefaultCachedMethodKey(org.codehaus.groovy.runtime.DefaultCachedMethodKey) MethodKey(org.codehaus.groovy.runtime.MethodKey) DefaultCachedMethodKey(org.codehaus.groovy.runtime.DefaultCachedMethodKey)

Example 3 with ClosureMetaMethod

use of org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod in project groovy-core by groovy.

the class MetaClassImpl method invokeMissingProperty.

/**
     * Invoke a missing property on the given object with the given arguments.
     *
     * @param instance The object the method should be invoked on.
     * @param propertyName The name of the property to invoke.
     * @param optionalValue The (optional) new value for the property
     * @param isGetter Wether the method is a getter
     *
     * @return The result of the method invocation.
     */
public Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
    Class theClass = instance instanceof Class ? (Class) instance : instance.getClass();
    CachedClass superClass = theCachedClass;
    while (superClass != null && superClass != ReflectionCache.OBJECT_CLASS) {
        final MetaBeanProperty property = findPropertyInClassHierarchy(propertyName, superClass);
        if (property != null) {
            onSuperPropertyFoundInHierarchy(property);
            if (!isGetter) {
                property.setProperty(instance, optionalValue);
                return null;
            } else {
                return property.getProperty(instance);
            }
        }
        superClass = superClass.getCachedSuperClass();
    }
    // got here to property not found, look for getProperty or setProperty overrides
    if (isGetter) {
        final Class[] getPropertyArgs = { String.class };
        final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), GET_PROPERTY_METHOD, getPropertyArgs, this);
        if (method != null && method instanceof ClosureMetaMethod) {
            onGetPropertyFoundInHierarchy(method);
            return method.invoke(instance, new Object[] { propertyName });
        }
    } else {
        final Class[] setPropertyArgs = { String.class, Object.class };
        final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), SET_PROPERTY_METHOD, setPropertyArgs, this);
        if (method != null && method instanceof ClosureMetaMethod) {
            onSetPropertyFoundInHierarchy(method);
            return method.invoke(instance, new Object[] { propertyName, optionalValue });
        }
    }
    try {
        if (!(instance instanceof Class)) {
            if (isGetter && propertyMissingGet != null) {
                return propertyMissingGet.invoke(instance, new Object[] { propertyName });
            } else {
                if (propertyMissingSet != null)
                    return propertyMissingSet.invoke(instance, new Object[] { propertyName, optionalValue });
            }
        }
    } catch (InvokerInvocationException iie) {
        boolean shouldHandle = isGetter && propertyMissingGet != null;
        if (!shouldHandle)
            shouldHandle = !isGetter && propertyMissingSet != null;
        if (shouldHandle && iie.getCause() instanceof MissingPropertyException) {
            throw (MissingPropertyException) iie.getCause();
        }
        throw iie;
    }
    if (instance instanceof Class && theClass != Class.class) {
        final MetaProperty metaProperty = InvokerHelper.getMetaClass(Class.class).hasProperty(instance, propertyName);
        if (metaProperty != null)
            if (isGetter)
                return metaProperty.getProperty(instance);
            else {
                metaProperty.setProperty(instance, optionalValue);
                return null;
            }
    }
    throw new MissingPropertyExceptionNoStack(propertyName, theClass);
}
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) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) MissingPropertyExceptionNoStack(org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack) InvokerInvocationException(org.codehaus.groovy.runtime.InvokerInvocationException) CachedClass(org.codehaus.groovy.reflection.CachedClass) CachedClass(org.codehaus.groovy.reflection.CachedClass) GetMethodMetaProperty(org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty) GetBeanMethodMetaProperty(org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty)

Example 4 with ClosureMetaMethod

use of org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod in project groovy-core by groovy.

the class MetaClassImpl method invokeMissingMethod.

private Object invokeMissingMethod(Object instance, String methodName, Object[] arguments, RuntimeException original, boolean isCallToSuper) {
    if (!isCallToSuper) {
        Class instanceKlazz = instance.getClass();
        if (theClass != instanceKlazz && theClass.isAssignableFrom(instanceKlazz))
            instanceKlazz = theClass;
        Class[] argClasses = MetaClassHelper.castArgumentsToClassArray(arguments);
        MetaMethod method = findMixinMethod(methodName, argClasses);
        if (method != null) {
            onMixinMethodFound(method);
            return method.invoke(instance, arguments);
        }
        method = findMethodInClassHierarchy(instanceKlazz, methodName, argClasses, this);
        if (method != null) {
            onSuperMethodFoundInHierarchy(method);
            return method.invoke(instance, arguments);
        }
        // still not method here, so see if there is an invokeMethod method up the hierarchy
        final Class[] invokeMethodArgs = { String.class, Object[].class };
        method = findMethodInClassHierarchy(instanceKlazz, INVOKE_METHOD_METHOD, invokeMethodArgs, this);
        if (method != null && method instanceof ClosureMetaMethod) {
            onInvokeMethodFoundInHierarchy(method);
            return method.invoke(instance, invokeMethodArgs);
        }
    }
    if (methodMissing != null) {
        try {
            return methodMissing.invoke(instance, new Object[] { methodName, arguments });
        } catch (InvokerInvocationException iie) {
            if (methodMissing instanceof ClosureMetaMethod && iie.getCause() instanceof MissingMethodException) {
                MissingMethodException mme = (MissingMethodException) iie.getCause();
                throw new MissingMethodExecutionFailed(mme.getMethod(), mme.getClass(), mme.getArguments(), mme.isStatic(), mme);
            }
            throw iie;
        } catch (MissingMethodException mme) {
            if (methodMissing instanceof ClosureMetaMethod)
                throw new MissingMethodExecutionFailed(mme.getMethod(), mme.getClass(), mme.getArguments(), mme.isStatic(), mme);
            else
                throw mme;
        }
    } else if (original != null)
        throw original;
    else
        throw new MissingMethodExceptionNoStack(methodName, theClass, arguments, 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) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) MissingMethodExceptionNoStack(org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack) InvokerInvocationException(org.codehaus.groovy.runtime.InvokerInvocationException) CachedClass(org.codehaus.groovy.reflection.CachedClass) MissingMethodExecutionFailed(org.codehaus.groovy.runtime.metaclass.MissingMethodExecutionFailed)

Example 5 with ClosureMetaMethod

use of org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod in project groovy by apache.

the class ExpandoMetaClass method addSuperMethodIfNotOverridden.

private void addSuperMethodIfNotOverridden(final MetaMethod metaMethodFromSuper) {
    performOperationOnMetaClass(new Callable() {

        public void call() {
            MetaMethod existing = null;
            try {
                existing = pickMethod(metaMethodFromSuper.getName(), metaMethodFromSuper.getNativeParameterTypes());
            } catch (GroovyRuntimeException e) {
            // ignore, this happens with overlapping method definitions
            }
            if (existing == null) {
                addMethodWithKey(metaMethodFromSuper);
            } else {
                boolean isGroovyMethod = getMetaMethods().contains(existing);
                if (isGroovyMethod) {
                    addMethodWithKey(metaMethodFromSuper);
                } else if (inheritedMetaMethods.contains(existing)) {
                    inheritedMetaMethods.remove(existing);
                    addMethodWithKey(metaMethodFromSuper);
                }
            }
        }

        private void addMethodWithKey(final MetaMethod metaMethodFromSuper) {
            inheritedMetaMethods.add(metaMethodFromSuper);
            if (metaMethodFromSuper instanceof ClosureMetaMethod) {
                ClosureMetaMethod closureMethod = (ClosureMetaMethod) metaMethodFromSuper;
                String name = metaMethodFromSuper.getName();
                final Class declaringClass = metaMethodFromSuper.getDeclaringClass().getTheClass();
                ClosureMetaMethod localMethod = ClosureMetaMethod.copy(closureMethod);
                addMetaMethod(localMethod);
                MethodKey key = new DefaultCachedMethodKey(declaringClass, name, localMethod.getParameterTypes(), false);
                checkIfGroovyObjectMethod(localMethod);
                expandoMethods.put(key, localMethod);
            }
        }
    });
}
Also used : ClosureStaticMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureStaticMetaMethod) MixinInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) OwnedMetaClass(org.codehaus.groovy.runtime.metaclass.OwnedMetaClass) MixedInMetaClass(org.codehaus.groovy.runtime.metaclass.MixedInMetaClass) CachedClass(org.codehaus.groovy.reflection.CachedClass) MixinInMetaClass(org.codehaus.groovy.reflection.MixinInMetaClass) DefaultCachedMethodKey(org.codehaus.groovy.runtime.DefaultCachedMethodKey) MethodKey(org.codehaus.groovy.runtime.MethodKey) DefaultCachedMethodKey(org.codehaus.groovy.runtime.DefaultCachedMethodKey)

Aggregations

CachedClass (org.codehaus.groovy.reflection.CachedClass)6 ClosureMetaMethod (org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod)6 MixinInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod)6 GeneratedMetaMethod (org.codehaus.groovy.reflection.GeneratedMetaMethod)4 InvokerInvocationException (org.codehaus.groovy.runtime.InvokerInvocationException)4 NewInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod)4 NewMetaMethod (org.codehaus.groovy.runtime.metaclass.NewMetaMethod)4 NewStaticMetaMethod (org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod)4 TransformMetaMethod (org.codehaus.groovy.runtime.metaclass.TransformMetaMethod)4 MixinInMetaClass (org.codehaus.groovy.reflection.MixinInMetaClass)2 DefaultCachedMethodKey (org.codehaus.groovy.runtime.DefaultCachedMethodKey)2 MethodKey (org.codehaus.groovy.runtime.MethodKey)2 ClosureStaticMetaMethod (org.codehaus.groovy.runtime.metaclass.ClosureStaticMetaMethod)2 GetBeanMethodMetaProperty (org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty)2 GetMethodMetaProperty (org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty)2 MissingMethodExceptionNoStack (org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack)2 MissingMethodExecutionFailed (org.codehaus.groovy.runtime.metaclass.MissingMethodExecutionFailed)2 MissingPropertyExceptionNoStack (org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack)2 MixedInMetaClass (org.codehaus.groovy.runtime.metaclass.MixedInMetaClass)2 OwnedMetaClass (org.codehaus.groovy.runtime.metaclass.OwnedMetaClass)2