cn.taketoday.aop.cglib.proxy.InterfaceMaker Maven / Gradle / Ivy
/*
* Copyright 2004 The Apache Software Foundation
*
* 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 cn.taketoday.aop.cglib.proxy;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import cn.taketoday.aop.Constant;
import cn.taketoday.aop.cglib.core.AbstractClassGenerator;
import cn.taketoday.aop.cglib.core.ClassEmitter;
import cn.taketoday.aop.cglib.core.ReflectUtils;
import cn.taketoday.aop.cglib.core.Signature;
import cn.taketoday.context.asm.ClassVisitor;
import cn.taketoday.context.asm.Type;
/**
* Generates new interfaces at runtime. By passing a generated interface to the
* Enhancer's list of interfaces to implement, you can make your enhanced
* classes handle an arbitrary set of method signatures.
*
* @author Chris Nokleberg
* @version $Id: InterfaceMaker.java,v 1.4 2006/03/05 02:43:19 herbyderby Exp $
*/
@SuppressWarnings("all")
public class InterfaceMaker extends AbstractClassGenerator {
private static final Source SOURCE = new Source(InterfaceMaker.class.getName());
private Map signatures = new HashMap();
/**
* Create a new InterfaceMaker
. A new InterfaceMaker
* object should be used for each generated interface, and should not be shared
* across threads.
*/
public InterfaceMaker() {
super(SOURCE);
}
/**
* Add a method signature to the interface.
*
* @param sig
* the method signature to add to the interface
* @param exceptions
* an array of exception types to declare for the method
*/
public void add(Signature sig, Type[] exceptions) {
signatures.put(sig, exceptions);
}
/**
* Add a method signature to the interface. The method modifiers are ignored,
* since interface methods are by definition abstract and public.
*
* @param method
* the method to add to the interface
*/
public void add(Method method) {
add(ReflectUtils.getSignature(method), ReflectUtils.getExceptionTypes(method));
}
/**
* Add all the public methods in the specified class. Methods from superclasses
* are included, except for methods declared in the base Object class (e.g.
* getClass
, equals
, hashCode
).
*
* @param class
* the class containing the methods to add to the interface
*/
public void add(Class clazz) {
Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (!m.getDeclaringClass().getName().equals("java.lang.Object")) {
add(m);
}
}
}
/**
* Create an interface using the current set of method signatures.
*/
public Class create() {
setUseCache(false);
return (Class) super.create(this);
}
protected ClassLoader getDefaultClassLoader() {
return null;
}
protected Object firstInstance(Class type) {
return type;
}
protected Object nextInstance(Object instance) {
throw new IllegalStateException("InterfaceMaker does not cache");
}
@Override
public void generateClass(ClassVisitor v) throws Exception {
ClassEmitter ce = new ClassEmitter(v);
ce.begin_class(Constant.V1_2, Constant.ACC_PUBLIC | Constant.ACC_INTERFACE, getClassName(), null, null,
Constant.SOURCE_FILE);
for (Iterator it = signatures.keySet().iterator(); it.hasNext();) {
Signature sig = (Signature) it.next();
Type[] exceptions = (Type[]) signatures.get(sig);
ce.begin_method(Constant.ACC_PUBLIC | Constant.ACC_ABSTRACT, sig, exceptions).end_method();
}
ce.end_class();
}
}