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);
}
}
}
}
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;
}
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;
}
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;
}
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);
}
}));
}
Aggregations