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 }