use of org.springframework.cglib.core.ClassEmitter in project spring-framework by spring-projects.
the class Enhancer method emitMethods.
private void emitMethods(final ClassEmitter ce, List methods, List actualMethods) {
CallbackGenerator[] generators = CallbackInfo.getGenerators(callbackTypes);
Map groups = new HashMap();
final Map indexes = new HashMap();
final Map originalModifiers = new HashMap();
final Map positions = CollectionUtils.getIndexMap(methods);
final Map declToBridge = new HashMap();
Iterator it1 = methods.iterator();
Iterator it2 = (actualMethods != null) ? actualMethods.iterator() : null;
while (it1.hasNext()) {
MethodInfo method = (MethodInfo) it1.next();
Method actualMethod = (it2 != null) ? (Method) it2.next() : null;
int index = filter.accept(actualMethod);
if (index >= callbackTypes.length) {
throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index);
}
originalModifiers.put(method, (actualMethod != null ? actualMethod.getModifiers() : method.getModifiers()));
indexes.put(method, index);
List group = (List) groups.get(generators[index]);
if (group == null) {
groups.put(generators[index], group = new ArrayList(methods.size()));
}
group.add(method);
// so that we can look up all the bridge methods in one pass for a class.
if (TypeUtils.isBridge(actualMethod.getModifiers())) {
Set bridges = (Set) declToBridge.get(actualMethod.getDeclaringClass());
if (bridges == null) {
bridges = new HashSet();
declToBridge.put(actualMethod.getDeclaringClass(), bridges);
}
bridges.add(method.getSignature());
}
}
final Map bridgeToTarget = new BridgeMethodResolver(declToBridge, getClassLoader()).resolveAll();
Set seenGen = new HashSet();
CodeEmitter se = ce.getStaticHook();
se.new_instance(THREAD_LOCAL);
se.dup();
se.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL);
se.putfield(THREAD_CALLBACKS_FIELD);
final Object[] state = new Object[1];
CallbackGenerator.Context context = new CallbackGenerator.Context() {
public ClassLoader getClassLoader() {
return Enhancer.this.getClassLoader();
}
public int getOriginalModifiers(MethodInfo method) {
return ((Integer) originalModifiers.get(method)).intValue();
}
public int getIndex(MethodInfo method) {
return ((Integer) indexes.get(method)).intValue();
}
public void emitCallback(CodeEmitter e, int index) {
emitCurrentCallback(e, index);
}
public Signature getImplSignature(MethodInfo method) {
return rename(method.getSignature(), ((Integer) positions.get(method)).intValue());
}
public void emitLoadArgsAndInvoke(CodeEmitter e, MethodInfo method) {
// If this is a bridge and we know the target was called from invokespecial,
// then we need to invoke_virtual w/ the bridge target instead of doing
// a super, because super may itself be using super, which would bypass
// any proxies on the target.
Signature bridgeTarget = (Signature) bridgeToTarget.get(method.getSignature());
if (bridgeTarget != null) {
// checkcast each argument against the target's argument types
for (int i = 0; i < bridgeTarget.getArgumentTypes().length; i++) {
e.load_arg(i);
Type target = bridgeTarget.getArgumentTypes()[i];
if (!target.equals(method.getSignature().getArgumentTypes()[i])) {
e.checkcast(target);
}
}
e.invoke_virtual_this(bridgeTarget);
Type retType = method.getSignature().getReturnType();
// method.)
if (!retType.equals(bridgeTarget.getReturnType())) {
e.checkcast(retType);
}
} else {
e.load_args();
e.super_invoke(method.getSignature());
}
}
public CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method) {
CodeEmitter e = EmitUtils.begin_method(ce, method);
if (!interceptDuringConstruction && !TypeUtils.isAbstract(method.getModifiers())) {
Label constructed = e.make_label();
e.load_this();
e.getfield(CONSTRUCTED_FIELD);
e.if_jump(CodeEmitter.NE, constructed);
e.load_this();
e.load_args();
e.super_invoke();
e.return_value();
e.mark(constructed);
}
return e;
}
};
for (int i = 0; i < callbackTypes.length; i++) {
CallbackGenerator gen = generators[i];
if (!seenGen.contains(gen)) {
seenGen.add(gen);
final List fmethods = (List) groups.get(gen);
if (fmethods != null) {
try {
gen.generate(ce, context, fmethods);
gen.generateStatic(se, context, fmethods);
} catch (RuntimeException x) {
throw x;
} catch (Exception x) {
throw new CodeGenerationException(x);
}
}
}
}
se.return_value();
se.end_method();
}
use of org.springframework.cglib.core.ClassEmitter in project spring-framework by spring-projects.
the class Enhancer method generateClass.
public void generateClass(ClassVisitor v) throws Exception {
Class sc = (superclass == null) ? Object.class : superclass;
if (TypeUtils.isFinal(sc.getModifiers()))
throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
filterConstructors(sc, constructors);
// Order is very important: must add superclass, then
// its superclass chain, then each interface and
// its superinterfaces.
List actualMethods = new ArrayList();
List interfaceMethods = new ArrayList();
final Set forcePublic = new HashSet();
getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);
List methods = CollectionUtils.transform(actualMethods, new Transformer() {
public Object transform(Object value) {
Method method = (Method) value;
int modifiers = Constants.ACC_FINAL | (method.getModifiers() & ~Constants.ACC_ABSTRACT & ~Constants.ACC_NATIVE & ~Constants.ACC_SYNCHRONIZED);
if (forcePublic.contains(MethodWrapper.create(method))) {
modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
}
return ReflectUtils.getMethodInfo(method, modifiers);
}
});
ClassEmitter e = new ClassEmitter(v);
if (currentData == null) {
e.begin_class(Constants.V1_8, Constants.ACC_PUBLIC, getClassName(), Type.getType(sc), (useFactory ? TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) : TypeUtils.getTypes(interfaces)), Constants.SOURCE_FILE);
} else {
e.begin_class(Constants.V1_8, Constants.ACC_PUBLIC, getClassName(), null, new Type[] { FACTORY }, Constants.SOURCE_FILE);
}
List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null);
if (!interceptDuringConstruction) {
e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);
}
e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
if (serialVersionUID != null) {
e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
}
for (int i = 0; i < callbackTypes.length; i++) {
e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
}
// This is declared private to avoid "public field" pollution
e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, CALLBACK_FILTER_FIELD, OBJECT_TYPE, null);
if (currentData == null) {
emitMethods(e, methods, actualMethods);
emitConstructors(e, constructorInfo);
} else {
emitDefaultConstructor(e);
}
emitSetThreadCallbacks(e);
emitSetStaticCallbacks(e);
emitBindCallbacks(e);
if (useFactory || currentData != null) {
int[] keys = getCallbackKeys();
emitNewInstanceCallbacks(e);
emitNewInstanceCallback(e);
emitNewInstanceMultiarg(e, constructorInfo);
emitGetCallback(e, keys);
emitSetCallback(e, keys);
emitGetCallbacks(e);
emitSetCallbacks(e);
}
e.end_class();
}
Aggregations