package org.reflections.adapters;
import com.google.common.base.Joiner;
import static javassist.bytecode.AccessFlag.*;
import com.google.common.collect.Lists;
import javassist.bytecode.*;
import javassist.bytecode.annotation.Annotation;
import org.reflections.ReflectionsException;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
*/
public class JavassistAdapter implements MetadataAdapter<ClassFile, FieldInfo, MethodInfo> {
public List<FieldInfo> getFields(final ClassFile cls) {
//noinspection unchecked
return cls.getFields();
}
public List<MethodInfo> getMethods(final ClassFile cls) {
//noinspection unchecked
return cls.getMethods();
}
public String getMethodName(final MethodInfo method) {
return method.getName();
}
public List<String> getParameterNames(final MethodInfo method) {
String descriptor = method.getDescriptor();
descriptor = descriptor.substring(descriptor.indexOf("(") + 1, descriptor.lastIndexOf(")"));
return splitDescriptorToTypeNames(descriptor);
}
public List<String> getClassAnnotationNames(final ClassFile aClass) {
AnnotationsAttribute annotationsAttribute = (AnnotationsAttribute) aClass.getAttribute(AnnotationsAttribute.visibleTag);
return getAnnotationNames(annotationsAttribute);
}
public List<String> getFieldAnnotationNames(final FieldInfo field) {
AnnotationsAttribute annotationsAttribute = (AnnotationsAttribute) field.getAttribute(AnnotationsAttribute.visibleTag);
return getAnnotationNames(annotationsAttribute);
}
public List<String> getMethodAnnotationNames(final MethodInfo method) {
AnnotationsAttribute annotationsAttribute = (AnnotationsAttribute) method.getAttribute(AnnotationsAttribute.visibleTag);
return getAnnotationNames(annotationsAttribute);
}
public List<String> getParameterAnnotationNames(final MethodInfo method, final int parameterIndex) {
ParameterAnnotationsAttribute parameterAnnotationsAttribute = (ParameterAnnotationsAttribute) method.getAttribute(ParameterAnnotationsAttribute.visibleTag);
if (parameterAnnotationsAttribute != null) {
Annotation[][] annotations = parameterAnnotationsAttribute.getAnnotations();
Annotation[] annotation = annotations[parameterIndex];
return getAnnotationNames(annotation);
} else {
return new ArrayList<String>();
}
}
public String getReturnTypeName(final MethodInfo method) {
String descriptor = method.getDescriptor();
descriptor = descriptor.substring(descriptor.lastIndexOf(")") + 1);
return splitDescriptorToTypeNames(descriptor).get(0);
}
public String getFieldName(final FieldInfo field) {
return field.getName();
}
public ClassFile createClassObject(InputStream inputStream) throws IOException {
DataInputStream dis = null;
try {
dis = new DataInputStream(new BufferedInputStream(inputStream));
return new ClassFile(dis);
} finally {
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
//noinspection ThrowFromFinallyBlock
throw new ReflectionsException("could not close DataInputStream", e);
}
}
}
}
public String getMethodModifier(MethodInfo method) {
int accessFlags = method.getAccessFlags();
return isPrivate(accessFlags) ? "private" :
isProtected(accessFlags) ? "protected" :
isPublic(accessFlags) ? "public" : "";
}
public String getMethodKey(ClassFile cls, MethodInfo method) {
return getMethodName(method) + "(" + Joiner.on(", ").join(getParameterNames(method)) + ")";
}
public String getMethodFullKey(ClassFile cls, MethodInfo method) {
return getClassName(cls) + "." + getMethodKey(cls, method);
}
//
public String getClassName(final ClassFile cls) {
return cls.getName();
}
public String getSuperclassName(final ClassFile cls) {
return cls.getSuperclass();
}
public List<String> getInterfacesNames(final ClassFile cls) {
return Arrays.asList(cls.getInterfaces());
}
//
private List<String> getAnnotationNames(final AnnotationsAttribute annotationsAttribute) {
if (annotationsAttribute == null) {return new ArrayList<String>(0);}
final Annotation[] annotations = annotationsAttribute.getAnnotations();
return getAnnotationNames(annotations);
}
private List<String> getAnnotationNames(final Annotation[] annotations) {
List<String> result = Lists.newArrayList();
for (Annotation annotation : annotations) {
result.add(annotation.getTypeName());
}
return result;
}
private List<String> splitDescriptorToTypeNames(final String descriptors) {
List<String> result = Lists.newArrayList();
if (descriptors != null && descriptors.length() != 0) {
List<Integer> indices = Lists.newArrayList();
Descriptor.Iterator iterator = new Descriptor.Iterator(descriptors);
while (iterator.hasNext()) {
indices.add(iterator.next());
}
indices.add(descriptors.length());
for (int i = 0; i < indices.size() - 1; i++) {
String s1 = Descriptor.toString(descriptors.substring(indices.get(i), indices.get(i + 1)));
result.add(s1);
}
}
return result;
}
}