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.relauncher.FMLRelauncher; 015 import cpw.mods.fml.relauncher.IClassTransformer; 016 import cpw.mods.fml.relauncher.SideOnly; 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 if (bytes == null) { return null; } 027 028 ClassNode classNode = new ClassNode(); 029 ClassReader classReader = new ClassReader(bytes); 030 classReader.accept(classNode, 0); 031 032 if (remove((List<AnnotationNode>)classNode.visibleAnnotations, SIDE)) 033 { 034 if (DEBUG) 035 { 036 System.out.println(String.format("Attempted to load class %s for invalid side %s", classNode.name, SIDE)); 037 } 038 throw new RuntimeException(String.format("Attempted to load class %s for invalid side %s", classNode.name, SIDE)); 039 } 040 041 Iterator<FieldNode> fields = classNode.fields.iterator(); 042 while(fields.hasNext()) 043 { 044 FieldNode field = fields.next(); 045 if (remove((List<AnnotationNode>)field.visibleAnnotations, SIDE)) 046 { 047 if (DEBUG) 048 { 049 System.out.println(String.format("Removing Field: %s.%s", classNode.name, field.name)); 050 } 051 fields.remove(); 052 } 053 } 054 Iterator<MethodNode> methods = classNode.methods.iterator(); 055 while(methods.hasNext()) 056 { 057 MethodNode method = methods.next(); 058 if (remove((List<AnnotationNode>)method.visibleAnnotations, SIDE)) 059 { 060 if (DEBUG) 061 { 062 System.out.println(String.format("Removing Method: %s.%s%s", classNode.name, method.name, method.desc)); 063 } 064 methods.remove(); 065 } 066 } 067 068 ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); 069 classNode.accept(writer); 070 return writer.toByteArray(); 071 } 072 073 private boolean remove(List<AnnotationNode> anns, String side) 074 { 075 if (anns == null) 076 { 077 return false; 078 } 079 for (AnnotationNode ann : anns) 080 { 081 if (ann.desc.equals(Type.getDescriptor(SideOnly.class))) 082 { 083 if (ann.values != null) 084 { 085 for (int x = 0; x < ann.values.size() - 1; x += 2) 086 { 087 Object key = ann.values.get(x); 088 Object value = ann.values.get(x+1); 089 if (key instanceof String && key.equals("value")) 090 { 091 if (value instanceof String[] ) 092 { 093 if (!((String[])value)[1].equals(side)) 094 { 095 return true; 096 } 097 } 098 } 099 } 100 } 101 } 102 } 103 return false; 104 } 105 }