package net.sourceforge.javautil.interceptor.type;
import java.util.List;
import java.util.Map;
import net.sourceforge.javautil.bytecode.BytecodeCompiler;
import net.sourceforge.javautil.bytecode.api.MethodDescriptor;
import net.sourceforge.javautil.bytecode.api.TypeDescriptor;
import net.sourceforge.javautil.bytecode.api.TypeMemberAccess.Scope;
import net.sourceforge.javautil.bytecode.api.type.BytecodeContextType;
import net.sourceforge.javautil.bytecode.api.type.JavaClassConcrete;
import net.sourceforge.javautil.bytecode.api.type.method.BytecodeBlock;
import net.sourceforge.javautil.bytecode.api.type.method.BytecodeContextMethod;
import net.sourceforge.javautil.interceptor.IInterceptorManager;
import net.sourceforge.javautil.interceptor.IInterceptorManipulator;
import net.sourceforge.javautil.interceptor.type.cjc.InterceptorProxyConstructor;
/**
* The base for the different CJC (Concrete Java Class) proxy types. Implementations must provide
* a constructor that matches the constructor signature provided by this base class.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public abstract class InterceptorProxyTypeInterceptor extends InterceptorProxyTypeAbstract {
public static final String CACHE_FIELD_NAME = "cache";
public static final String INTERCEPTOR_FIELD_NAME = "interceptor";
public static final String ABILITIES_FIELD_NAME = "abilities";
protected final Class type;
protected List<IInterceptorManipulator> abilities;
public InterceptorProxyTypeInterceptor(BytecodeCompiler compiler, List<IInterceptorManipulator> abilities, Class type, String name) {
super(compiler, type, name);
this.type = type;
this.setSuperType(type);
this.addInstanceField(INTERCEPTOR_FIELD_NAME, IInterceptorManager.class, Scope.Private, true);
this.addInstanceField(CACHE_FIELD_NAME, Map.class, Scope.Private, true);
if (abilities != null && abilities.size() > 0) {
this.addInstanceField(ABILITIES_FIELD_NAME, Map.class, Scope.Private, true);
this.abilities = abilities;
}
this.addMethod("set$Interceptor", Scope.Private, false, true, new MethodDescriptor(false, null, null, IInterceptorManager.class))
.setMethodBody(new BytecodeBlock() {
@Override protected void writeInstructions(BytecodeContextMethod context) {
context.set("this", INTERCEPTOR_FIELD_NAME, context.getDeclaredParameter(0));
}
});
}
/**
* Add the constructors for this proxy type
*/
public abstract void addProxyConstructors ();
/**
* Add the methods for intercepting calls
*/
public abstract void addProxyMethods ();
/**
* Allow any manipulators to add additional functionality.
*/
public void addProxyAbilities() {
if (abilities != null && abilities.size() != 0) {
for (int i=0; i<abilities.size(); i++) {
abilities.get(i).manipulate(type, this,
this.getField(compiler.getPool(), INTERCEPTOR_FIELD_NAME),
this.getField(compiler.getPool(), ABILITIES_FIELD_NAME)
);
}
}
}
}