Ejemplo n.º 1
0
  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;
  }