use of org.gradle.model.internal.asm.AsmClassGenerator in project gradle by gradle.
the class ManagedCollectionProxyClassGenerator method generate.
/**
* Generates an implementation of the given managed type.
*
* <p>The generated type will:</p>
*
* <ul>
* <li>extend the given implementation class</li>
* <li>implement the given public interface</li>
* <li>override each public constructor of the given implementation class</li>
* </ul>
*/
public Class<?> generate(Class<?> implClass, Class<?> publicContractType) {
AsmClassGenerator classGenerator = new AsmClassGenerator(publicContractType, "_Impl");
ClassWriter visitor = classGenerator.getVisitor();
Type generatedType = classGenerator.getGeneratedType();
Type superclassType = Type.getType(implClass);
Type publicType = Type.getType(publicContractType);
generateClass(visitor, generatedType, superclassType, publicType);
generateConstructors(visitor, implClass, superclassType);
visitor.visitEnd();
return classGenerator.define();
}
use of org.gradle.model.internal.asm.AsmClassGenerator in project gradle by gradle.
the class ManagedProxyClassGenerator method generate.
/**
* Generates an implementation of the given managed type.
* <p>
* The generated class will implement/extend the managed type and will:
* <ul>
* <li>provide implementations for abstract getters and setters that delegate to the backing state</li>
* <li>provide a `toString()` implementation</li>
* <li>mix-in implementation of {@link ManagedInstance}</li>
* <li>provide a constructor that accepts a {@link ModelElementState}, which will be used to implement the above.</li>
* </ul>
*
* In case a delegate schema is supplied, the generated class will also have:
* <ul>
* <li>a constructor that also takes a delegate instance</li>
* <li>methods that call through to the delegate instance</li>
* </ul>
*/
public <T, M extends T, D extends T> Class<? extends M> generate(Class<? extends GeneratedViewState> backingStateType, StructSchema<M> viewSchema, StructBindings<?> structBindings) {
if (!structBindings.getImplementedViewSchemas().contains(viewSchema)) {
throw new IllegalArgumentException(String.format("View '%s' is not supported by struct '%s'", viewSchema.getType(), structBindings.getPublicSchema().getType()));
}
ModelType<M> viewType = viewSchema.getType();
StringBuilder generatedTypeNameBuilder = new StringBuilder();
if (backingStateType == GeneratedViewState.class) {
generatedTypeNameBuilder.append("$View");
} else {
generatedTypeNameBuilder.append("$NodeView");
}
StructSchema<D> delegateSchema = Cast.uncheckedCast(structBindings.getDelegateSchema());
if (delegateSchema != null) {
generatedTypeNameBuilder.append("$").append(delegateSchema.getType().getName().replaceAll("\\.", "_"));
}
String classNameSuffix = generatedTypeNameBuilder.toString();
Class<?> superclass;
final ImmutableSet.Builder<String> interfacesToImplement = ImmutableSet.builder();
final ImmutableSet.Builder<ModelType<?>> typesToDelegate = ImmutableSet.builder();
typesToDelegate.add(viewType);
interfacesToImplement.add(GENERATED_VIEW_TYPE.getInternalName());
if (backingStateType == ModelElementState.class) {
interfacesToImplement.add(MANAGED_INSTANCE_TYPE);
}
Class<M> viewClass = viewType.getConcreteClass();
if (viewClass.isInterface()) {
superclass = Object.class;
interfacesToImplement.add(Type.getInternalName(viewClass));
} else {
superclass = viewClass;
}
// BinaryContainer won't recognize managed binaries as BinarySpecInternal
if (delegateSchema != null) {
walkTypeHierarchy(delegateSchema.getType().getConcreteClass(), IGNORED_OBJECT_TYPES, new TypeVisitor<D>() {
@Override
public void visitType(Class<? super D> type) {
if (type.isInterface()) {
typesToDelegate.add(ModelType.of(type));
interfacesToImplement.add(Type.getInternalName(type));
}
}
});
}
ClassLoader targetClassLoader = viewClass.getClassLoader();
if (delegateSchema != null) {
// TODO - remove this once the above is removed
try {
viewClass.getClassLoader().loadClass(delegateSchema.getType().getConcreteClass().getName());
} catch (ClassNotFoundException e) {
// Delegate class is not visible to managed view type -> view type is more general than delegate type, so use the delegate classloader instead
targetClassLoader = delegateSchema.getType().getConcreteClass().getClassLoader();
}
}
AsmClassGenerator generator = new AsmClassGenerator(viewClass, classNameSuffix);
ClassWriter visitor = generator.getVisitor();
generateProxyClass(visitor, viewSchema, structBindings, interfacesToImplement.build(), typesToDelegate.build(), generator.getGeneratedType(), Type.getType(superclass), backingStateType);
return generator.define(targetClassLoader);
}
use of org.gradle.model.internal.asm.AsmClassGenerator in project gradle by gradle.
the class NamedObjectInstantiator method loaderFor.
private ClassGeneratingLoader loaderFor(Class<?> publicClass) {
//
// Generate implementation class
//
FormattingValidationProblemCollector problemCollector = new FormattingValidationProblemCollector("Named implementation class", ModelType.of(publicClass));
visitFields(publicClass, problemCollector);
if (problemCollector.hasProblems()) {
throw new GradleException(problemCollector.format());
}
AsmClassGenerator generator = new AsmClassGenerator(publicClass, "$Impl");
Type implementationType = generator.getGeneratedType();
ClassWriter visitor = generator.getVisitor();
Type publicType = Type.getType(publicClass);
Type superClass;
String[] interfaces;
if (publicClass.isInterface()) {
superClass = OBJECT;
interfaces = new String[] { publicType.getInternalName(), MANAGED.getInternalName() };
} else {
superClass = publicType;
interfaces = INTERFACES_FOR_ABSTRACT_CLASS;
}
visitor.visit(V1_5, ACC_PUBLIC | ACC_SYNTHETIC, implementationType.getInternalName(), null, superClass.getInternalName(), interfaces);
//
// Add name field
//
visitor.visitField(ACC_PRIVATE, NAME_FIELD, STRING.getDescriptor(), null, null);
//
// Add constructor
//
MethodVisitor methodVisitor = visitor.visitMethod(ACC_PUBLIC, CONSTRUCTOR_NAME, RETURN_VOID_FROM_STRING, null, EMPTY_STRINGS);
methodVisitor.visitCode();
// Call this.super()
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superClass.getInternalName(), CONSTRUCTOR_NAME, RETURN_VOID, false);
// Set this.name = param1
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, implementationType.getInternalName(), NAME_FIELD, STRING.getDescriptor());
// Done
methodVisitor.visitInsn(Opcodes.RETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
//
// Add `getName()`
//
methodVisitor = visitor.visitMethod(ACC_PUBLIC, "getName", RETURN_STRING, null, EMPTY_STRINGS);
methodVisitor.visitCode();
// return this.name
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitFieldInsn(Opcodes.GETFIELD, implementationType.getInternalName(), NAME_FIELD, STRING.getDescriptor());
methodVisitor.visitInsn(Opcodes.ARETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
//
// Add `toString()`
//
methodVisitor = visitor.visitMethod(ACC_PUBLIC, "toString", RETURN_STRING, null, EMPTY_STRINGS);
methodVisitor.visitCode();
// return this.name
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitFieldInsn(Opcodes.GETFIELD, implementationType.getInternalName(), NAME_FIELD, STRING.getDescriptor());
methodVisitor.visitInsn(Opcodes.ARETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
visitor.visitEnd();
generator.define();
//
// Generate factory class
//
generator = new AsmClassGenerator(publicClass, "$Factory");
visitor = generator.getVisitor();
visitor.visit(V1_5, ACC_PUBLIC | ACC_SYNTHETIC, generator.getGeneratedType().getInternalName(), null, CLASS_GENERATING_LOADER.getInternalName(), EMPTY_STRINGS);
//
// Add constructor
//
methodVisitor = visitor.visitMethod(ACC_PUBLIC, CONSTRUCTOR_NAME, RETURN_VOID, null, EMPTY_STRINGS);
methodVisitor.visitCode();
// Call this.super()
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, CLASS_GENERATING_LOADER.getInternalName(), CONSTRUCTOR_NAME, RETURN_VOID, false);
// Done
methodVisitor.visitInsn(Opcodes.RETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
//
// Add factory method
//
methodVisitor = visitor.visitMethod(ACC_PUBLIC, "load", RETURN_OBJECT_FROM_STRING, null, EMPTY_STRINGS);
methodVisitor.visitCode();
// Call return new <implClass>(param1)
methodVisitor.visitTypeInsn(Opcodes.NEW, implementationType.getInternalName());
methodVisitor.visitInsn(Opcodes.DUP);
methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, implementationType.getInternalName(), CONSTRUCTOR_NAME, RETURN_VOID_FROM_STRING, false);
methodVisitor.visitInsn(Opcodes.ARETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
visitor.visitEnd();
Class<Object> factoryClass = generator.define();
try {
return (ClassGeneratingLoader) (factoryClass.newInstance());
} catch (Exception e) {
throw UncheckedException.throwAsUncheckedException(e);
}
}
Aggregations