package de.take_weiland.mods.commons.asm.info; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.io.ByteStreams; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Type; import java.io.IOException; import java.io.InputStream; import java.util.List; import static org.objectweb.asm.Opcodes.*; /** * @author diesieben07 */ final class ClassInfoReflect extends ClassInfo { private final Class<?> clazz; private List<String> interfaces; ClassInfoReflect(Class<?> clazz) { this.clazz = clazz; } @Override public List<String> interfaces() { if (interfaces == null) { ImmutableList.Builder<String> builder = ImmutableList.builder(); for (Class<?> iface : clazz.getInterfaces()) { builder.add(Type.getInternalName(iface)); } interfaces = builder.build(); } return interfaces; } @Override public String superName() { Class<?> s = clazz.getSuperclass(); return s == null ? null : Type.getInternalName(s); } @Override public String internalName() { return Type.getInternalName(clazz); } @Override public int modifiers() { return clazz.getModifiers(); } @Override public int getDimensions() { if (clazz.isArray()) { return StringUtils.countMatches(clazz.getName(), "["); } else { return 0; } } @Override boolean callRightAssignableFrom(ClassInfo parent) { return parent.isAssignableFromReflect(this); } @Override boolean isAssignableFromReflect(ClassInfoReflect child) { // use JDK test if both are reflectively loaded return this.clazz.isAssignableFrom(child.clazz); } private String sourceFileCache; @Override public String getSourceFile() { if (sourceFileCache == null) { InputStream in = clazz.getResourceAsStream('/' + clazz.getName().replace('.', '/') + ".class"); if (in != null) { try { ClassReader cr = new ClassReader(ByteStreams.toByteArray(in)); SourceFileExtractor extractor = new SourceFileExtractor(); cr.accept(extractor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); sourceFileCache = Strings.nullToEmpty(extractor.sourceFile); } catch (IOException e) { sourceFileCache = ""; } finally { IOUtils.closeQuietly(in); } } } return Strings.emptyToNull(sourceFileCache); } private static final class SourceFileExtractor extends ClassVisitor { String sourceFile; SourceFileExtractor() { super(ASM4, null); } @Override public void visitSource(String source, String debug) { sourceFile = source; super.visitSource(source, debug); } } }