Version 1.7.4
[gae.git] / java / src / main / com / google / appengine / tools / development / agent / impl / ReflectionVisitor.java
blob3d8f7f1f0b621492fc5a3331b6adf2ec15b98eca
1 // Copyright 2009 Google Inc. All Rights Reserved.
3 package com.google.appengine.tools.development.agent.impl;
5 import org.objectweb.asm.ClassVisitor;
6 import org.objectweb.asm.MethodVisitor;
7 import org.objectweb.asm.Opcodes;
8 import org.objectweb.asm.Type;
9 import org.objectweb.asm.commons.GeneratorAdapter;
11 import java.util.Map;
12 import java.util.Set;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.Arrays;
17 /**
18 * Intercepts reflective operations and adds checks against the WhiteList.
21 public class ReflectionVisitor extends ClassVisitor {
23 public ReflectionVisitor(final ClassVisitor classVisitor) {
24 super(Opcodes.ASM4, classVisitor);
27 private static final Map<String, Set<String>> interceptedMethods =
28 new HashMap<String,Set<String>>();
30 static {
31 interceptedMethods.put("java/lang/reflect/Method",
32 new HashSet<String>(Arrays.asList("invoke")));
34 interceptedMethods.put("java/lang/reflect/Field",
35 new HashSet<String>(Arrays.asList(
36 "get",
37 "getBoolean",
38 "getByte",
39 "getChar",
40 "getDouble",
41 "getFloat",
42 "getInt",
43 "getLong",
44 "getShort",
45 "set",
46 "setBoolean",
47 "setByte",
48 "setChar",
49 "setDouble",
50 "setFloat",
51 "setInt",
52 "setLong",
53 "setShort"
54 )));
56 interceptedMethods.put("java/lang/reflect/Constructor",
57 new HashSet<String>(Arrays.asList(
58 "newInstance"
59 )));
61 interceptedMethods.put("java/lang/Class",
62 new HashSet<String>(Arrays.asList(
63 "newInstance"
64 )));
67 @Override
68 public MethodVisitor visitMethod(int access, String name, String desc, String signature,
69 String[] exceptions) {
70 MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
71 return (mv == null) ? null : new MethodTranslator(mv, access, name, desc);
74 private class MethodTranslator extends GeneratorAdapter {
75 MethodTranslator(MethodVisitor methodVisitor, int access, String name, String desc) {
76 super(methodVisitor, access, name, desc);
79 @Override
80 public void visitMethodInsn(int opcode, String owner, String name, String desc) {
81 Set<String> methods = interceptedMethods.get(owner);
82 if (methods == null || !methods.contains(name)) {
83 super.visitMethodInsn(opcode, owner, name, desc);
84 return;
87 String newDesc = desc;
89 if (opcode == Opcodes.INVOKEVIRTUAL) {
90 final Type[] argTypes = Type.getArgumentTypes(desc);
91 final Type[] newArgTypes = new Type[argTypes.length + 1];
92 newArgTypes[0] = Type.getType("L" + owner + ";");
93 System.arraycopy(argTypes, 0, newArgTypes, 1, argTypes.length);
94 newDesc = Type.getMethodDescriptor(Type.getReturnType(desc), newArgTypes);
97 super.visitMethodInsn(Opcodes.INVOKESTATIC, AgentImpl.AGENT_RUNTIME, name, newDesc);