001 package cpw.mods.fml.common.discovery.asm; 002 003 import java.io.IOException; 004 import java.io.InputStream; 005 import java.util.Collections; 006 import java.util.LinkedList; 007 import java.util.List; 008 import java.util.logging.Level; 009 010 import net.minecraft.src.BaseMod; 011 012 import org.objectweb.asm.ClassReader; 013 import org.objectweb.asm.Type; 014 015 import com.google.common.base.Objects; 016 import com.google.common.collect.Lists; 017 018 import cpw.mods.fml.common.FMLLog; 019 import cpw.mods.fml.common.LoaderException; 020 import cpw.mods.fml.common.discovery.ASMDataTable; 021 import cpw.mods.fml.common.discovery.ModCandidate; 022 023 public class ASMModParser 024 { 025 026 private Type asmType; 027 private int classVersion; 028 private Type asmSuperType; 029 private LinkedList<ModAnnotation> annotations = Lists.newLinkedList(); 030 private String baseModProperties; 031 032 static enum AnnotationType 033 { 034 CLASS, FIELD, METHOD, SUBTYPE; 035 } 036 037 public ASMModParser(InputStream stream) throws IOException 038 { 039 try 040 { 041 ClassReader reader = new ClassReader(stream); 042 reader.accept(new ModClassVisitor(this), 0); 043 } 044 catch (Exception ex) 045 { 046 FMLLog.log(Level.SEVERE, ex, "Unable to read a class file correctly"); 047 throw new LoaderException(ex); 048 } 049 } 050 051 public void beginNewTypeName(String typeQName, int classVersion, String superClassQName) 052 { 053 this.asmType = Type.getObjectType(typeQName); 054 this.classVersion = classVersion; 055 this.asmSuperType = Type.getObjectType(superClassQName); 056 } 057 058 public void startClassAnnotation(String annotationName) 059 { 060 ModAnnotation ann = new ModAnnotation(AnnotationType.CLASS, Type.getType(annotationName), this.asmType.getClassName()); 061 annotations.addFirst(ann); 062 } 063 064 public void addAnnotationProperty(String key, Object value) 065 { 066 annotations.getFirst().addProperty(key, value); 067 } 068 069 public void startFieldAnnotation(String fieldName, String annotationName) 070 { 071 ModAnnotation ann = new ModAnnotation(AnnotationType.FIELD, Type.getType(annotationName), fieldName); 072 annotations.addFirst(ann); 073 } 074 075 @Override 076 public String toString() 077 { 078 return Objects.toStringHelper("ASMAnnotationDiscoverer") 079 .add("className", asmType.getClassName()) 080 .add("classVersion", classVersion) 081 .add("superName", asmSuperType.getClassName()) 082 .add("annotations", annotations) 083 .add("isBaseMod", isBaseMod(Collections.<String>emptyList())) 084 .add("baseModProperties", baseModProperties) 085 .toString(); 086 } 087 088 public Type getASMType() 089 { 090 return asmType; 091 } 092 093 public int getClassVersion() 094 { 095 return classVersion; 096 } 097 098 public Type getASMSuperType() 099 { 100 return asmSuperType; 101 } 102 103 public LinkedList<ModAnnotation> getAnnotations() 104 { 105 return annotations; 106 } 107 108 public void validate() 109 { 110 // if (classVersion > 50.0) 111 // { 112 // 113 // throw new LoaderException(new RuntimeException("Mod compiled for Java 7 detected")); 114 // } 115 } 116 117 public boolean isBaseMod(List<String> rememberedTypes) 118 { 119 return getASMSuperType().equals(Type.getType(BaseMod.class)) || rememberedTypes.contains(getASMSuperType().getClassName()); 120 } 121 122 public void setBaseModProperties(String foundProperties) 123 { 124 this.baseModProperties = foundProperties; 125 } 126 127 public String getBaseModProperties() 128 { 129 return this.baseModProperties; 130 } 131 132 public void sendToTable(ASMDataTable table, ModCandidate candidate) 133 { 134 for (ModAnnotation ma : annotations) 135 { 136 table.addASMData(candidate, ma.asmType.getClassName(), this.asmType.getClassName(), ma.member, ma.values); 137 } 138 } 139 140 public void addAnnotationArray(String name) 141 { 142 annotations.getFirst().addArray(name); 143 } 144 145 public void addAnnotationEnumProperty(String name, String desc, String value) 146 { 147 annotations.getFirst().addEnumProperty(name, desc, value); 148 149 } 150 151 public void endArray() 152 { 153 annotations.getFirst().endArray(); 154 155 } 156 157 public void addSubAnnotation(String name, String desc) 158 { 159 ModAnnotation ma = annotations.getFirst(); 160 annotations.addFirst(ma.addChildAnnotation(name, desc)); 161 } 162 163 public void endSubAnnotation() 164 { 165 // take the child and stick it at the end 166 ModAnnotation child = annotations.removeFirst(); 167 annotations.addLast(child); 168 } 169 }