Search in sources :

Example 11 with MetaClass

use of groovy.lang.MetaClass in project grails-core by grails.

the class GrailsMetaClassUtils method copyExpandoMetaClass.

/**
 * Copies the ExpandoMetaClass dynamic methods and properties from one Class to another.
 *
 * @param fromClass The source class
 * @param toClass  The destination class
 * @param removeSource Whether to remove the source class after completion. True if yes
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void copyExpandoMetaClass(Class<?> fromClass, Class<?> toClass, boolean removeSource) {
    MetaClassRegistry registry = getRegistry();
    MetaClass oldMetaClass = registry.getMetaClass(fromClass);
    AdaptingMetaClass adapter = null;
    ExpandoMetaClass emc;
    if (oldMetaClass instanceof AdaptingMetaClass) {
        adapter = ((AdaptingMetaClass) oldMetaClass);
        emc = (ExpandoMetaClass) adapter.getAdaptee();
        if (LOG.isDebugEnabled()) {
            LOG.debug("Obtained adapted MetaClass [" + emc + "] from AdapterMetaClass instance [" + adapter + "]");
        }
        if (removeSource) {
            registry.removeMetaClass(fromClass);
        }
    } else {
        emc = (ExpandoMetaClass) oldMetaClass;
        if (LOG.isDebugEnabled()) {
            LOG.debug("No adapter MetaClass found, using original [" + emc + "]");
        }
    }
    ExpandoMetaClass replacement = new ExpandoMetaClass(toClass, true, true);
    for (Object obj : emc.getExpandoMethods()) {
        if (obj instanceof ClosureInvokingMethod) {
            ClosureInvokingMethod cim = (ClosureInvokingMethod) obj;
            Closure callable = cim.getClosure();
            if (!cim.isStatic()) {
                replacement.setProperty(cim.getName(), callable);
            } else {
                ((GroovyObject) replacement.getProperty(ExpandoMetaClass.STATIC_QUALIFIER)).setProperty(cim.getName(), callable);
            }
        }
    }
    for (Object o : emc.getExpandoProperties()) {
        if (o instanceof ThreadManagedMetaBeanProperty) {
            ThreadManagedMetaBeanProperty mbp = (ThreadManagedMetaBeanProperty) o;
            replacement.setProperty(mbp.getName(), mbp.getInitialValue());
        }
    }
    replacement.initialize();
    if (adapter == null) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Adding MetaClass for class [" + toClass + "] MetaClass [" + replacement + "]");
        }
        registry.setMetaClass(toClass, replacement);
    } else {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Adding MetaClass for class [" + toClass + "] MetaClass [" + replacement + "] with adapter [" + adapter + "]");
        }
        try {
            Constructor c = adapter.getClass().getConstructor(new Class[] { MetaClass.class });
            MetaClass newAdapter = (MetaClass) BeanUtils.instantiateClass(c, new Object[] { replacement });
            registry.setMetaClass(toClass, newAdapter);
        } catch (NoSuchMethodException e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Exception thrown constructing new MetaClass adapter when reloading: " + e.getMessage(), e);
            }
        }
    }
}
Also used : MetaClassRegistry(groovy.lang.MetaClassRegistry) MetaClass(groovy.lang.MetaClass) ExpandoMetaClass(groovy.lang.ExpandoMetaClass) AdaptingMetaClass(groovy.lang.AdaptingMetaClass) DelegatingMetaClass(groovy.lang.DelegatingMetaClass) Closure(groovy.lang.Closure) ThreadManagedMetaBeanProperty(org.codehaus.groovy.runtime.metaclass.ThreadManagedMetaBeanProperty) Constructor(java.lang.reflect.Constructor) ClosureInvokingMethod(groovy.lang.ClosureInvokingMethod) GroovyObject(groovy.lang.GroovyObject) ExpandoMetaClass(groovy.lang.ExpandoMetaClass) AdaptingMetaClass(groovy.lang.AdaptingMetaClass) GroovyObject(groovy.lang.GroovyObject)

Example 12 with MetaClass

use of groovy.lang.MetaClass in project grails-core by grails.

the class GrailsMetaClassUtils method invokeMethodIfExists.

/**
 * Invokes a method if it exists otherwise returns null
 *
 * @param instance The instance
 * @param methodName The method name
 * @param args The arguments
 *
 * @return The result of the method call or null
 */
public static Object invokeMethodIfExists(Object instance, String methodName, Object[] args) {
    MetaClass metaClass = getMetaClass(instance);
    List<MetaMethod> methodList = metaClass.respondsTo(instance, methodName, args);
    if (methodList != null && !methodList.isEmpty()) {
        return metaClass.invokeMethod(instance, methodName, args);
    }
    return null;
}
Also used : MetaMethod(groovy.lang.MetaMethod) MetaClass(groovy.lang.MetaClass) ExpandoMetaClass(groovy.lang.ExpandoMetaClass) AdaptingMetaClass(groovy.lang.AdaptingMetaClass) DelegatingMetaClass(groovy.lang.DelegatingMetaClass)

Example 13 with MetaClass

use of groovy.lang.MetaClass in project grails-core by grails.

the class GrailsClassUtils method getExpandoMetaClass.

@SuppressWarnings("rawtypes")
public static MetaClass getExpandoMetaClass(Class clazz) {
    MetaClassRegistry registry = GroovySystem.getMetaClassRegistry();
    Assert.isTrue(registry.getMetaClassCreationHandler() instanceof ExpandoMetaClassCreationHandle, "Grails requires an instance of [ExpandoMetaClassCreationHandle] to be set in Groovy's MetaClassRegistry! (current is : " + registry.getMetaClassCreationHandler() + ")");
    MetaClass mc = registry.getMetaClass(clazz);
    AdaptingMetaClass adapter = null;
    if (mc instanceof AdaptingMetaClass) {
        adapter = (AdaptingMetaClass) mc;
        mc = ((AdaptingMetaClass) mc).getAdaptee();
    }
    if (!(mc instanceof ExpandoMetaClass)) {
        // removes cached version
        registry.removeMetaClass(clazz);
        mc = registry.getMetaClass(clazz);
        if (adapter != null) {
            adapter.setAdaptee(mc);
        }
    }
    Assert.isTrue(mc instanceof ExpandoMetaClass, "BUG! Method must return an instance of [ExpandoMetaClass]!");
    return mc;
}
Also used : MetaClassRegistry(groovy.lang.MetaClassRegistry) ExpandoMetaClass(groovy.lang.ExpandoMetaClass) MetaClass(groovy.lang.MetaClass) AdaptingMetaClass(groovy.lang.AdaptingMetaClass) ExpandoMetaClassCreationHandle(groovy.lang.ExpandoMetaClassCreationHandle) ExpandoMetaClass(groovy.lang.ExpandoMetaClass) AdaptingMetaClass(groovy.lang.AdaptingMetaClass)

Example 14 with MetaClass

use of groovy.lang.MetaClass in project grails-core by grails.

the class GrailsClassUtils method findPropertyNameForValue.

/**
 * Locates the name of a property for the given value on the target object using Groovy's meta APIs.
 * Note that this method uses the reference so the incorrect result could be returned for two properties
 * that refer to the same reference. Use with caution.
 *
 * @param target The target
 * @param obj The property value
 * @return The property name or null
 */
public static String findPropertyNameForValue(Object target, Object obj) {
    MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass());
    List<MetaProperty> metaProperties = mc.getProperties();
    for (MetaProperty metaProperty : metaProperties) {
        if (isAssignableOrConvertibleFrom(metaProperty.getType(), obj.getClass())) {
            Object val = metaProperty.getProperty(target);
            if (val != null && val.equals(obj)) {
                return metaProperty.getName();
            }
        }
    }
    return null;
}
Also used : ExpandoMetaClass(groovy.lang.ExpandoMetaClass) MetaClass(groovy.lang.MetaClass) AdaptingMetaClass(groovy.lang.AdaptingMetaClass) ConfigObject(groovy.util.ConfigObject) MetaProperty(groovy.lang.MetaProperty)

Example 15 with MetaClass

use of groovy.lang.MetaClass in project groovy-core by groovy.

the class Verifier method addStaticMetaClassField.

private void addStaticMetaClassField(final ClassNode node, final String classInternalName) {
    String _staticClassInfoFieldName = "$staticClassInfo";
    while (node.getDeclaredField(_staticClassInfoFieldName) != null) _staticClassInfoFieldName = _staticClassInfoFieldName + "$";
    final String staticMetaClassFieldName = _staticClassInfoFieldName;
    FieldNode staticMetaClassField = node.addField(staticMetaClassFieldName, ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, ClassHelper.make(ClassInfo.class, false), null);
    staticMetaClassField.setSynthetic(true);
    node.addSyntheticMethod("$getStaticMetaClass", ACC_PROTECTED, ClassHelper.make(MetaClass.class), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

        public void visit(MethodVisitor mv) {
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
            if (BytecodeHelper.isClassLiteralPossible(node) || BytecodeHelper.isSameCompilationUnit(classNode, node)) {
                BytecodeHelper.visitClassLiteral(mv, node);
            } else {
                mv.visitMethodInsn(INVOKESTATIC, classInternalName, "$get$$class$" + classInternalName.replaceAll("\\/", "\\$"), "()Ljava/lang/Class;", false);
            }
            Label l1 = new Label();
            mv.visitJumpInsn(IF_ACMPEQ, l1);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/ScriptBytecodeAdapter", "initMetaClass", "(Ljava/lang/Object;)Lgroovy/lang/MetaClass;", false);
            mv.visitInsn(ARETURN);
            mv.visitLabel(l1);
            mv.visitFieldInsn(GETSTATIC, classInternalName, staticMetaClassFieldName, "Lorg/codehaus/groovy/reflection/ClassInfo;");
            mv.visitVarInsn(ASTORE, 1);
            mv.visitVarInsn(ALOAD, 1);
            Label l0 = new Label();
            mv.visitJumpInsn(IFNONNULL, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
            mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/reflection/ClassInfo", "getClassInfo", "(Ljava/lang/Class;)Lorg/codehaus/groovy/reflection/ClassInfo;", false);
            mv.visitInsn(DUP);
            mv.visitVarInsn(ASTORE, 1);
            mv.visitFieldInsn(PUTSTATIC, classInternalName, staticMetaClassFieldName, "Lorg/codehaus/groovy/reflection/ClassInfo;");
            mv.visitLabel(l0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEVIRTUAL, "org/codehaus/groovy/reflection/ClassInfo", "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
            mv.visitInsn(ARETURN);
        }
    }));
}
Also used : MetaClass(groovy.lang.MetaClass) Label(org.objectweb.asm.Label) ClassInfo(org.codehaus.groovy.reflection.ClassInfo) MethodVisitor(org.objectweb.asm.MethodVisitor)

Aggregations

MetaClass (groovy.lang.MetaClass)141 DelegatingMetaClass (groovy.lang.DelegatingMetaClass)62 GroovyObject (groovy.lang.GroovyObject)62 ExpandoMetaClass (groovy.lang.ExpandoMetaClass)40 MetaClassImpl (groovy.lang.MetaClassImpl)18 MetaProperty (groovy.lang.MetaProperty)12 GroovyRuntimeException (groovy.lang.GroovyRuntimeException)11 MetaMethod (groovy.lang.MetaMethod)11 ArrayList (java.util.ArrayList)11 MixinInMetaClass (org.codehaus.groovy.reflection.MixinInMetaClass)11 AdaptingMetaClass (groovy.lang.AdaptingMetaClass)9 MetaClassRegistry (groovy.lang.MetaClassRegistry)9 Map (java.util.Map)9 GString (groovy.lang.GString)7 CachedClass (org.codehaus.groovy.reflection.CachedClass)7 ClassInfo (org.codehaus.groovy.reflection.ClassInfo)7 MissingMethodException (groovy.lang.MissingMethodException)6 MissingPropertyException (groovy.lang.MissingPropertyException)6 IOException (java.io.IOException)6 Method (java.lang.reflect.Method)6