001 package cpw.mods.fml.common.asm.transformers; 002 003 import java.util.Iterator; 004 import java.util.List; 005 006 import org.objectweb.asm.ClassReader; 007 import org.objectweb.asm.ClassWriter; 008 import org.objectweb.asm.Type; 009 import org.objectweb.asm.tree.AnnotationNode; 010 import org.objectweb.asm.tree.ClassNode; 011 import org.objectweb.asm.tree.FieldNode; 012 import org.objectweb.asm.tree.MethodNode; 013 014 import cpw.mods.fml.common.asm.SideOnly; 015 import cpw.mods.fml.relauncher.FMLRelauncher; 016 import cpw.mods.fml.relauncher.IClassTransformer; 017 018 public class SideTransformer implements IClassTransformer 019 { 020 private static String SIDE = FMLRelauncher.side(); 021 private static final boolean DEBUG = false; 022 @SuppressWarnings("unchecked") 023 @Override 024 public byte[] transform(String name, byte[] bytes) 025 { 026 ClassNode classNode = new ClassNode(); 027 ClassReader classReader = new ClassReader(bytes); 028 classReader.accept(classNode, 0); 029 030 if (remove((List<AnnotationNode>)classNode.visibleAnnotations, SIDE)) 031 { 032 if (DEBUG) 033 { 034 System.out.println(String.format("Attempted to load class %s for invalid side %s", classNode.name, SIDE)); 035 } 036 return null; 037 } 038 039 Iterator<FieldNode> fields = classNode.fields.iterator(); 040 while(fields.hasNext()) 041 { 042 FieldNode field = fields.next(); 043 if (remove((List<AnnotationNode>)field.visibleAnnotations, SIDE)) 044 { 045 if (DEBUG) 046 { 047 System.out.println(String.format("Removing Field: %s.%s", classNode.name, field.name)); 048 } 049 fields.remove(); 050 } 051 } 052 Iterator<MethodNode> methods = classNode.methods.iterator(); 053 while(methods.hasNext()) 054 { 055 MethodNode method = methods.next(); 056 if (remove((List<AnnotationNode>)method.visibleAnnotations, SIDE)) 057 { 058 if (DEBUG) 059 { 060 System.out.println(String.format("Removing Method: %s.%s%s", classNode.name, method.name, method.desc)); 061 } 062 methods.remove(); 063 } 064 } 065 066 ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); 067 classNode.accept(writer); 068 return writer.toByteArray(); 069 } 070 071 private boolean remove(List<AnnotationNode> anns, String side) 072 { 073 if (anns == null) 074 { 075 return false; 076 } 077 for (AnnotationNode ann : anns) 078 { 079 if (ann.desc.equals(Type.getDescriptor(SideOnly.class))) 080 { 081 if (ann.values != null) 082 { 083 for (int x = 0; x < ann.values.size() - 1; x += 2) 084 { 085 Object key = ann.values.get(x); 086 Object value = ann.values.get(x+1); 087 if (key instanceof String && key.equals("value")) 088 { 089 if (value instanceof String[] ) 090 { 091 if (!((String[])value)[1].equals(side)) 092 { 093 return true; 094 } 095 } 096 } 097 } 098 } 099 } 100 } 101 return false; 102 } 103 }