View Javadoc

1   /***
2    * 
3    */
4   package org.vafer.dependency.resources.runtime;
5   
6   import java.util.HashSet;
7   import java.util.Set;
8   
9   import org.objectweb.asm.ClassAdapter;
10  import org.objectweb.asm.ClassVisitor;
11  import org.objectweb.asm.MethodAdapter;
12  import org.objectweb.asm.MethodVisitor;
13  import org.objectweb.asm.Opcodes;
14  import org.vafer.dependency.asm.Remapper;
15  import org.vafer.dependency.resources.ResolverUtils;
16  
17  final class RuntimeResourceResolvingClassAdapter extends ClassAdapter implements Opcodes {
18  		
19  		private final String runimeClass = "org/vafer/dependency/resources/runtime/Mapper";
20  		private final Remapper mapper;
21  		private String current;
22  	
23  		public RuntimeResourceResolvingClassAdapter( final ClassVisitor cv, final Remapper pMapper ) {
24  			super(cv);
25  			mapper = pMapper;
26  		}
27  
28  		public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
29  			super.visit(version, access, name, signature, superName, interfaces);
30  	
31  			current = name;
32  		}
33  	
34  		public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
35  	
36  			final MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
37  	
38  			return new MethodWrapper(mv);
39  		}
40  	
41  		private class MethodWrapper extends MethodAdapter {
42  	
43  			private final MethodVisitor mv;
44  	
45  			public MethodWrapper(final MethodVisitor pMv) {
46  				super(pMv);
47  				mv = pMv;
48  			}
49  				
50  
51  			private void inject( MethodVisitor mv, String method ) {
52  
53  				// "old"				
54  				mv.visitTypeInsn(NEW, "java/lang/StringBuffer");
55  				// "old", stringbuffer
56  				mv.visitInsn(DUP);
57  				// "old", stringbuffer, stringbuffer
58  				mv.visitLdcInsn(mapper.map(""));
59  				// "old", stringbuffer, stringbuffer, "prefix"
60  				mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuffer", "<init>", "(Ljava/lang/String;)V");
61  				// "old", stringbuffer
62  				mv.visitInsn(DUP2);
63  				// "old", stringbuffer, "old", stringbuffer
64                  mv.visitInsn(POP);
65  				// "old", stringbuffer, "old"
66  				mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
67  				// "old", stringbuffer
68  				mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "toString", "()Ljava/lang/String;");				
69  				// "old", "prefixold"
70  				mv.visitMethodInsn(INVOKESTATIC, runimeClass, method, "(Ljava/lang/String;)Ljava/lang/String;");
71  				// "old", "prefixnew"
72  				mv.visitInsn(SWAP);
73  				// "prefixnew", "old"
74  				mv.visitInsn(POP);
75  				// "prefixnew"
76  			}
77  			
78  			public void visitMethodInsn(int opcode, String owner, String name, String desc) {
79  				
80  				if (ResolverUtils.needsResourceResolving(owner, name)) {
81  
82  					System.out.println("Wrapping resource access " + name + " in " + current);
83  					
84  					inject(mv, "resolveResource");
85  										
86  				} else if (ResolverUtils.needsClassResolving(owner, name)) {
87  
88  					System.out.println("Wrapping class access " + name + " in " + current);
89  
90  					inject(mv, "resolveClass");
91  					
92  				}
93  
94  				mv.visitMethodInsn(opcode, owner, name, desc);
95  			}
96  		}
97  }