package icecaptools;
import java.io.DataInputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.AnnotationEntry;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ElementValue;
import org.apache.bcel.classfile.ElementValuePair;
import org.apache.bcel.classfile.RuntimeInvisibleAnnotations;
import org.apache.bcel.classfile.Visitor;
public class AnnotationsAttribute extends Attribute {
/**
*
*/
private static final long serialVersionUID = 1L;
private HashMap<String, HashMap<String, String>> annotations;
public AnnotationsAttribute(int nameIndex, int length, ConstantPool cp) {
super(Constants.ATTR_UNKNOWN, nameIndex, length, cp);
annotations = new HashMap<String, HashMap<String, String>>();
}
public void read(DataInputStream in, ConstantPool cp) throws IOException {
short numAnnotations = in.readShort();
for (int i = 0; i < numAnnotations; i++) {
short typeIndex = in.readShort();
String type = cp.constantToString(cp.getConstant(typeIndex));
HashMap<String, String> nvPairs = new HashMap<String, String>();
annotations.put(type.replace("/", "."), nvPairs);
short numElementValuePairs = in.readShort();
for (int j = 0; j < numElementValuePairs; j++) {
short nameIndex = in.readShort();
String name = cp.constantToString(cp.getConstant(nameIndex));
byte tag = in.readByte();
if (tag == 's') {
short constValueIndex = in.readShort();
String value = cp.constantToString(cp.getConstant(constValueIndex));
nvPairs.put(name, value);
} else if (tag == 'e') {
in.readShort();
in.readShort();
} else {
throw new UnsupportedOperationException("Unknown attribute type attributes");
}
}
}
}
public static AnnotationsAttribute getAttribute(
RuntimeInvisibleAnnotations attribute) {
AnnotationsAttribute aattr = new AnnotationsAttribute(attribute.getNameIndex(), attribute.getLength(), attribute.getConstantPool());
int numAnnotations = attribute.getNumAnnotations();
for (int i = 0; i < numAnnotations; i++) {
AnnotationEntry ae = attribute.getAnnotationEntries()[i];
String type = ae.getAnnotationType();
HashMap<String, String> nvPairs = new HashMap<String, String>();
aattr.annotations.put(type.replace("/", "."), nvPairs);
int numElementValuePairs = ae.getNumElementValuePairs();
for (int j = 0; j < numElementValuePairs; j++) {
ElementValuePair nextPair = ae.getElementValuePairs()[j];
String name = nextPair.getNameString();
ElementValue evalue = nextPair.getValue();
String value = evalue.stringifyValue();
nvPairs.put(name, value);
}
}
return aattr;
}
@Override
public void accept(Visitor v) {
throw new UnsupportedOperationException();
}
@Override
public Attribute copy(ConstantPool _constant_pool) {
throw new UnsupportedOperationException();
}
@Override
public String toString() {
return annotations.toString();
}
@SuppressWarnings("unchecked")
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
String key = "L" + annotationClass.getName().replace("/", ".") + ";";
final HashMap<String, String> nvPairs = annotations.get(key);
if (nvPairs == null)
return null;
InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, java.lang.reflect.Method m, Object[] args) throws Throwable {
return nvPairs.get(m.getName());
}
};
return (A) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { annotationClass }, handler);
}
}