/* * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.gradle.model.internal.manage.schema.extract; import org.gradle.model.internal.asm.AsmClassGenerator; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import java.lang.reflect.Constructor; public class ManagedCollectionProxyClassGenerator extends AbstractProxyClassGenerator { /** * 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(); } private <T> void generateConstructors(ClassWriter visitor, Class<? extends T> implClass, Type superclassType) { for (Constructor<?> constructor : implClass.getConstructors()) { Type[] paramTypes = new Type[constructor.getParameterTypes().length]; for (int i = 0; i < paramTypes.length; i++) { paramTypes[i] = Type.getType(constructor.getParameterTypes()[i]); } String methodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, paramTypes); MethodVisitor constructorVisitor = visitor.visitMethod(Opcodes.ACC_PUBLIC, CONSTRUCTOR_NAME, methodDescriptor, CONCRETE_SIGNATURE, NO_EXCEPTIONS); constructorVisitor.visitCode(); putThisOnStack(constructorVisitor); for (int i = 0; i < paramTypes.length; i++) { constructorVisitor.visitVarInsn(paramTypes[i].getOpcode(Opcodes.ILOAD), i + 1); } constructorVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superclassType.getInternalName(), CONSTRUCTOR_NAME, methodDescriptor, false); finishVisitingMethod(constructorVisitor); } } private void generateClass(ClassWriter visitor, Type generatedType, Type superclassType, Type publicType) { visitor.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, generatedType.getInternalName(), null, superclassType.getInternalName(), new String[]{publicType.getInternalName()}); } }