package org.deuce.transform.asm; import org.deuce.objectweb.asm.ClassAdapter; import org.deuce.objectweb.asm.ClassReader; import org.deuce.objectweb.asm.ClassWriter; import org.deuce.objectweb.asm.MethodVisitor; import org.deuce.objectweb.asm.commons.JSRInlinerAdapter; import org.deuce.transform.Exclude; /** * Adds frames to allow later {@link ClassReader#EXPAND_FRAMES} * @author Guy Korland * @since 1.0 */ @Exclude public class FramesCodeVisitor extends ClassAdapter{ final static private int JAVA5_VERSION = 49; final static private int JAVA6_VERSION = 50; public FramesCodeVisitor( String className) { super(new CommonClassWriter( ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES, className)); } @Override public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { if(version == JAVA6_VERSION) // already has frames throw VersionException.INSTANCE; super.visit(JAVA5_VERSION, access, name, signature, superName, interfaces); } public byte[] visit( byte[] bytes){ ClassReader cr = new ClassReader(bytes); cr.accept(this, 0); return ((ClassWriter)super.cv).toByteArray(); } @Override public MethodVisitor visitMethod( final int access, final String name, final String desc, final String signature, final String[] exceptions) { return new JSRInlinerAdapter( super.visitMethod(access, name, desc, signature, exceptions), access, name, desc, signature, exceptions); } @Exclude public static class VersionException extends RuntimeException{ private static final long serialVersionUID = 1L; final public static VersionException INSTANCE = new VersionException(); } /** * FIXME This is a work around and should be fixed better in the future. * By overriding the getCommonSuperClass we avoid loading * @author Guy Korland * */ @Exclude private static class CommonClassWriter extends ClassWriter{ public CommonClassWriter(int flags, String className) { super(flags); } @Override protected String getCommonSuperClass(final String type1, final String type2) { if( type1.equals(type2)) return type1; return "java/lang/Object"; } } }