use of org.gradle.api.provider.Property in project gradle by gradle.
the class AbstractClassGenerator method generateUnderLock.
private <T> Class<? extends T> generateUnderLock(Class<T> type) {
Map<Class<?>, Class<?>> cache = GENERATED_CLASSES.get(getClass());
if (cache == null) {
// WeakHashMap won't work here. It keeps a strong reference to the mapping value, which is the generated class in this case
// However, the generated class has a strong reference to the source class (by extending it), so the keys will always be
// strongly reachable while this Class is strongly reachable. Use weak references for both key and value of the mapping instead.
cache = new ReferenceMap(AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK);
GENERATED_CLASSES.put(getClass(), cache);
}
Class<?> generatedClass = cache.get(type);
if (generatedClass != null) {
return generatedClass.asSubclass(type);
}
int modifiers = type.getModifiers();
if (Modifier.isPrivate(modifiers)) {
throw new GradleException(String.format("Cannot create a proxy class for private class '%s'.", type.getSimpleName()));
}
if (Modifier.isAbstract(modifiers)) {
throw new GradleException(String.format("Cannot create a proxy class for abstract class '%s'.", type.getSimpleName()));
}
if (Modifier.isFinal(modifiers)) {
throw new GradleException(String.format("Cannot create a proxy class for final class '%s'.", type.getSimpleName()));
}
Class<? extends T> subclass;
try {
ClassMetaData classMetaData = inspectType(type);
ClassBuilder<T> builder = start(type, classMetaData);
builder.startClass(classMetaData.isShouldImplementWithServiceRegistry());
if (!DynamicObjectAware.class.isAssignableFrom(type)) {
if (ExtensionAware.class.isAssignableFrom(type)) {
throw new UnsupportedOperationException("A type that implements ExtensionAware must currently also implement DynamicObjectAware.");
}
builder.mixInDynamicAware();
}
if (!GroovyObject.class.isAssignableFrom(type)) {
builder.mixInGroovyObject();
}
builder.addDynamicMethods();
if (classMetaData.conventionAware && !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;
}
}
if (classMetaData.isShouldImplementWithServiceRegistry()) {
builder.generateServiceRegistrySupportMethods();
}
Set<PropertyMetaData> conventionProperties = new HashSet<PropertyMetaData>();
for (PropertyMetaData property : classMetaData.properties.values()) {
if (SKIP_PROPERTIES.contains(property.name)) {
continue;
}
if (!property.getters.isEmpty() && (Property.class.isAssignableFrom(property.getType()) || HasMultipleValues.class.isAssignableFrom(property.getType()))) {
builder.addPropertySetters(property, property.getters.get(0));
continue;
}
if (property.injector) {
builder.addInjectorProperty(property);
for (Method getter : property.getters) {
builder.applyServiceInjectionToGetter(property, getter);
}
for (Method setter : property.setters) {
builder.applyServiceInjectionToSetter(property, setter);
}
continue;
}
boolean needsConventionMapping = false;
if (classMetaData.isExtensible()) {
for (Method getter : property.getters) {
if (!Modifier.isFinal(getter.getModifiers()) && !getter.getDeclaringClass().isAssignableFrom(noMappingClass)) {
needsConventionMapping = true;
break;
}
}
}
if (needsConventionMapping) {
conventionProperties.add(property);
builder.addConventionProperty(property);
for (Method getter : property.getters) {
builder.applyConventionMappingToGetter(property, getter);
}
for (Method setter : property.setters) {
if (!Modifier.isFinal(setter.getModifiers())) {
builder.applyConventionMappingToSetter(property, setter);
}
}
}
}
Set<Method> actionMethods = classMetaData.missingOverloads;
for (Method method : actionMethods) {
builder.addActionMethod(method);
}
// Adds a set method for each mutable property
for (PropertyMetaData property : classMetaData.properties.values()) {
if (property.setters.isEmpty()) {
continue;
}
if (Iterable.class.isAssignableFrom(property.getType())) {
// Currently not supported
continue;
}
if (property.setMethods.isEmpty()) {
for (Method setter : property.setters) {
builder.addSetMethod(property, setter);
}
} else if (conventionProperties.contains(property)) {
for (Method setMethod : property.setMethods) {
builder.applyConventionMappingToSetMethod(property, setMethod);
}
}
}
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);
cache.put(subclass, subclass);
return subclass;
}
Aggregations