package org.glassfish.pfl.tf.tools.enhancer;
import org.glassfish.pfl.tf.spi.EnhancedClassData;
import org.glassfish.pfl.tf.spi.TraceEnhancementException;
import org.glassfish.pfl.tf.spi.annotation.TFEnhanced;
import org.glassfish.pfl.tf.spi.annotation.TraceEnhanceLevel;
import org.glassfish.pfl.objectweb.asm.AnnotationVisitor;
import org.glassfish.pfl.objectweb.asm.ClassAdapter;
import org.glassfish.pfl.objectweb.asm.ClassVisitor;
import org.glassfish.pfl.objectweb.asm.FieldVisitor;
import org.glassfish.pfl.objectweb.asm.MethodVisitor;
import org.glassfish.pfl.objectweb.asm.Type;
public class TFEnhanceAdapter extends ClassAdapter {
private static final String TFENHANCED_ANNO_DESC =
Type.getDescriptor( TFEnhanced.class ) ;
private static final String TRACE_ENHANCE_LEVEL_DESC =
Type.getDescriptor( TraceEnhanceLevel.class ) ;
private boolean firstCall = true ;
private final TraceEnhanceLevel[] present = new TraceEnhanceLevel[1] ;
private final TraceEnhanceLevel required ;
private final TraceEnhanceLevel result ;
private final EnhancedClassData ecd ;
public TFEnhanceAdapter( ClassVisitor cv, TraceEnhanceLevel required,
TraceEnhanceLevel result, EnhancedClassData ecd ) {
super( cv ) ;
this.required = required ;
this.result = result ;
this.ecd = ecd ;
present[0] = TraceEnhanceLevel.NONE ;
}
private void checkForTFEnhanceAnnotation() {
if (firstCall) {
firstCall = false ;
if (present[0] != required) {
throw new TraceEnhancementException(
"Class " + ecd.getClassName()
+ " has trace enhancement level " + present[0]
+ " but " + required + " is required.") ;
}
AnnotationVisitor av = super.visitAnnotation( TFENHANCED_ANNO_DESC,
true ) ;
av.visitEnum( "stage", TRACE_ENHANCE_LEVEL_DESC, result.name() ) ;
av.visitEnd() ;
}
}
@Override
public void visitInnerClass( String name,
String outerName, String innerName, int access ) {
checkForTFEnhanceAnnotation();
super.visitInnerClass( name, outerName, innerName, access ) ;
}
@Override
public FieldVisitor visitField( int access, String name, String desc,
String signature, Object value ) {
checkForTFEnhanceAnnotation();
return super.visitField(access, name, desc, signature, value) ;
}
@Override
public MethodVisitor visitMethod( int access, String name, String desc,
String signature, String[] exceptions ) {
checkForTFEnhanceAnnotation();
return super.visitMethod(access, name, desc, signature, exceptions) ;
}
@Override
public AnnotationVisitor visitAnnotation( String desc, boolean isVisible ) {
if (desc.equals( TFENHANCED_ANNO_DESC )) {
return new AnnotationVisitor() {
public void visit(String name, Object value) {
}
public void visitEnum(String name, String desc, String value) {
if (name.equals( "stage")) {
present[0] = Enum.valueOf( TraceEnhanceLevel.class,
value ) ;
}
}
public AnnotationVisitor visitAnnotation(String name,
String desc) {
return null ;
}
public AnnotationVisitor visitArray(String name) {
return null ;
}
public void visitEnd() {
}
} ;
} else {
final AnnotationVisitor av = super.visitAnnotation( desc, isVisible ) ;
return av ;
}
}
}