public static void mixinClassesToMetaClass(MetaClass self, List<Class> categoryClasses) { final Class selfClass = self.getTheClass(); if (self instanceof HandleMetaClass) { self = (MetaClass) ((HandleMetaClass) self).replaceDelegate(); } if (!(self instanceof ExpandoMetaClass)) { if (self instanceof DelegatingMetaClass && ((DelegatingMetaClass) self).getAdaptee() instanceof ExpandoMetaClass) { self = ((DelegatingMetaClass) self).getAdaptee(); } else { throw new GroovyRuntimeException("Can't mixin methods to meta class: " + self); } } ExpandoMetaClass mc = (ExpandoMetaClass) self; List<MetaMethod> arr = new ArrayList<MetaMethod>(); for (Class categoryClass : categoryClasses) { final CachedClass cachedCategoryClass = ReflectionCache.getCachedClass(categoryClass); final MixinInMetaClass mixin = new MixinInMetaClass(mc, cachedCategoryClass); final MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(categoryClass); final List<MetaProperty> propList = metaClass.getProperties(); for (MetaProperty prop : propList) if (self.getMetaProperty(prop.getName()) == null) { mc.registerBeanProperty(prop.getName(), new MixinInstanceMetaProperty(prop, mixin)); } for (MetaProperty prop : cachedCategoryClass.getFields()) if (self.getMetaProperty(prop.getName()) == null) { mc.registerBeanProperty(prop.getName(), new MixinInstanceMetaProperty(prop, mixin)); } for (MetaMethod method : metaClass.getMethods()) { final int mod = method.getModifiers(); if (!Modifier.isPublic(mod)) continue; if (method instanceof CachedMethod && ((CachedMethod) method).getCachedMethod().isSynthetic()) continue; if (Modifier.isStatic(mod)) { if (method instanceof CachedMethod) staticMethod(self, arr, (CachedMethod) method); } else if (method.getDeclaringClass().getTheClass() != Object.class || method.getName().equals("toString")) { // if (self.pickMethod(method.getName(), // method.getNativeParameterTypes()) == null) { final MixinInstanceMetaMethod metaMethod = new MixinInstanceMetaMethod(method, mixin); arr.add(metaMethod); // } } } } for (Object res : arr) { final MetaMethod metaMethod = (MetaMethod) res; if (metaMethod.getDeclaringClass().isAssignableFrom(selfClass)) mc.registerInstanceMethod(metaMethod); else { mc.registerSubclassInstanceMethod(metaMethod); } } }
public <T> Class<? extends T> generate(Class<T> type) { Map<Class, Class> cache = GENERATED_CLASSES.get(getClass()); if (cache == null) { cache = new HashMap<Class, Class>(); GENERATED_CLASSES.put(getClass(), cache); } Class generatedClass = cache.get(type); if (generatedClass != null) { return generatedClass; } if (Modifier.isPrivate(type.getModifiers())) { throw new GradleException( String.format( "Cannot create a proxy class for private class '%s'.", type.getSimpleName())); } if (Modifier.isAbstract(type.getModifiers())) { throw new GradleException( String.format( "Cannot create a proxy class for abstract class '%s'.", type.getSimpleName())); } Class<? extends T> subclass; try { ClassBuilder<T> builder = start(type); boolean isConventionAware = type.getAnnotation(NoConventionMapping.class) == null; boolean isDynamicAware = type.getAnnotation(NoDynamicObject.class) == null; builder.startClass(isConventionAware, isDynamicAware); if (isDynamicAware && !DynamicObjectAware.class.isAssignableFrom(type)) { builder.mixInDynamicAware(); } if (isDynamicAware && !GroovyObject.class.isAssignableFrom(type)) { builder.mixInGroovyObject(); } if (isDynamicAware) { builder.addDynamicMethods(); } if (isConventionAware && !IConventionAware.class.isAssignableFrom(type)) { builder.mixInConventionAware(); } Class noMappingClass = Object.class; for (Class<?> c = type; c != null && noMappingClass == Object.class; c = c.getSuperclass()) { if (c.getAnnotation(NoConventionMapping.class) != null) { noMappingClass = c; } } Collection<String> skipProperties = Arrays.asList("metaClass", "conventionMapping", "convention", "asDynamicObject"); MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(type); for (MetaProperty property : metaClass.getProperties()) { if (skipProperties.contains(property.getName())) { continue; } if (property instanceof MetaBeanProperty) { MetaBeanProperty metaBeanProperty = (MetaBeanProperty) property; MetaMethod getter = metaBeanProperty.getGetter(); if (getter == null) { continue; } if (Modifier.isFinal(getter.getModifiers()) || Modifier.isPrivate(getter.getModifiers())) { continue; } if (getter.getReturnType().isPrimitive()) { continue; } Class declaringClass = getter.getDeclaringClass().getTheClass(); if (declaringClass.isAssignableFrom(noMappingClass)) { continue; } builder.addGetter(metaBeanProperty); MetaMethod setter = metaBeanProperty.getSetter(); if (setter == null) { continue; } if (Modifier.isFinal(setter.getModifiers()) || Modifier.isPrivate(setter.getModifiers())) { continue; } builder.addSetter(metaBeanProperty); } } for (Constructor<?> constructor : type.getConstructors()) { if (Modifier.isPublic(constructor.getModifiers())) { builder.addConstructor(constructor); } } subclass = builder.generate(); } catch (Throwable e) { throw new GradleException( String.format("Could not generate a proxy class for class %s.", type.getName()), e); } cache.put(type, subclass); return subclass; }
public int getModifiers() { return method.getModifiers(); }