/* * * Copyright 2003 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.powermock.api.mockito.repackaged.cglib.proxy; import org.powermock.api.mockito.repackaged.asm.ClassVisitor; import org.powermock.api.mockito.repackaged.asm.Type; import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter; import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter; import org.powermock.api.mockito.repackaged.cglib.core.Constants; import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils; import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo; import org.powermock.api.mockito.repackaged.cglib.core.MethodWrapper; import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils; import org.powermock.api.mockito.repackaged.cglib.core.Signature; import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; /** * @author Chris Nokleberg * @version $Id: MixinEmitter.java,v 1.9 2006/08/27 21:04:37 herbyderby Exp $ */ class MixinEmitter extends ClassEmitter { private static final String FIELD_NAME = "CGLIB$DELEGATES"; private static final Signature CSTRUCT_OBJECT_ARRAY = TypeUtils.parseConstructor("Object[]"); private static final Type MIXIN = TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.Mixin"); private static final Signature NEW_INSTANCE = new Signature("newInstance", MIXIN, new Type[]{ Constants.TYPE_OBJECT_ARRAY }); public MixinEmitter(ClassVisitor v, String className, Class[] classes, int[] route) { super(v); begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, MIXIN, TypeUtils.getTypes(getInterfaces(classes)), Constants.SOURCE_FILE); EmitUtils.null_constructor(this); EmitUtils.factory_method(this, NEW_INSTANCE); declare_field(Constants.ACC_PRIVATE, FIELD_NAME, Constants.TYPE_OBJECT_ARRAY, null); CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null); e.load_this(); e.super_invoke_constructor(); e.load_this(); e.load_arg(0); e.putfield(FIELD_NAME); e.return_value(); e.end_method(); Set unique = new HashSet(); for (int i = 0; i < classes.length; i++) { Method[] methods = getMethods(classes[i]); for (int j = 0; j < methods.length; j++) { if (unique.add(MethodWrapper.create(methods[j]))) { MethodInfo method = ReflectUtils.getMethodInfo(methods[j]); e = EmitUtils.begin_method(this, method, Constants.ACC_PUBLIC); e.load_this(); e.getfield(FIELD_NAME); e.aaload((route != null) ? route[i] : i); e.checkcast(method.getClassInfo().getType()); e.load_args(); e.invoke(method); e.return_value(); e.end_method(); } } } end_class(); } protected Class[] getInterfaces(Class[] classes) { return classes; } protected Method[] getMethods(Class type) { return type.getMethods(); } }