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 }