11160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta/*
21160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta * Copyright (C) 2014 The Android Open Source Project
31160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta *
41160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta * Licensed under the Apache License, Version 2.0 (the "License");
51160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta * you may not use this file except in compliance with the License.
61160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta * You may obtain a copy of the License at
71160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta *
81160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta *      http://www.apache.org/licenses/LICENSE-2.0
91160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta *
101160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta * Unless required by applicable law or agreed to in writing, software
111160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta * distributed under the License is distributed on an "AS IS" BASIS,
121160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta * See the License for the specific language governing permissions and
141160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta * limitations under the License.
151160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta */
161160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta
171160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Guptapackage com.android.tools.layoutlib.create;
181160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta
191330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Guptaimport com.android.tools.layoutlib.java.LinkedHashMap_Delegate;
2017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport com.android.tools.layoutlib.java.System_Delegate;
2117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta
221160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Guptaimport org.objectweb.asm.ClassVisitor;
231160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Guptaimport org.objectweb.asm.MethodVisitor;
241160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Guptaimport org.objectweb.asm.Opcodes;
25b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Guptaimport org.objectweb.asm.Type;
261160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta
275cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Guptaimport java.util.ArrayList;
28e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Guptaimport java.util.Arrays;
29e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Guptaimport java.util.HashSet;
301330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Guptaimport java.util.LinkedHashMap;
315cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Guptaimport java.util.List;
32b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Guptaimport java.util.Locale;
331330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Guptaimport java.util.Map;
34e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Guptaimport java.util.Set;
35e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta
361160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta/**
375cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta * Replaces calls to certain methods that do not exist in the Desktop VM. Useful for methods in the
385cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta * "java" package.
391160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta */
401160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Guptapublic class ReplaceMethodCallsAdapter extends ClassVisitor {
41e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta
42e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta    /**
43e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta     * Descriptors for specialized versions {@link System#arraycopy} that are not present on the
44e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta     * Desktop VM.
45e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta     */
46e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta    private static Set<String> ARRAYCOPY_DESCRIPTORS = new HashSet<String>(Arrays.asList(
47e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta            "([CI[CII)V", "([BI[BII)V", "([SI[SII)V", "([II[III)V",
48e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta            "([JI[JII)V", "([FI[FII)V", "([DI[DII)V", "([ZI[ZII)V"));
49e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta
501330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta    private static final List<MethodReplacer> METHOD_REPLACERS = new ArrayList<MethodReplacer>(5);
515cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta
52b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta    private static final String ANDROID_LOCALE_CLASS =
53b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta            "com/android/layoutlib/bridge/android/AndroidLocale";
54b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta
5517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta    private static final String JAVA_LOCALE_CLASS = Type.getInternalName(java.util.Locale.class);
56b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta    private static final Type STRING = Type.getType(String.class);
57b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta
5817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta    private static final String JAVA_LANG_SYSTEM = Type.getInternalName(System.class);
5917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta
605cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta    // Static initialization block to initialize METHOD_REPLACERS.
615cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta    static {
625cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta        // Case 1: java.lang.System.arraycopy()
635cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta        METHOD_REPLACERS.add(new MethodReplacer() {
645cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            @Override
655cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            public boolean isNeeded(String owner, String name, String desc) {
6617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                return JAVA_LANG_SYSTEM.equals(owner) && "arraycopy".equals(name) &&
675cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta                        ARRAYCOPY_DESCRIPTORS.contains(desc);
685cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            }
695cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta
705cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            @Override
7117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            public void replace(MethodInformation mi) {
7217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                assert isNeeded(mi.owner, mi.name, mi.desc);
7317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                mi.desc = "(Ljava/lang/Object;ILjava/lang/Object;II)V";
745cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            }
755cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta        });
765cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta
77b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta        // Case 2: java.util.Locale.toLanguageTag() and java.util.Locale.getScript()
785cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta        METHOD_REPLACERS.add(new MethodReplacer() {
79b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta
801330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta            private final String LOCALE_TO_STRING =
811330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta                    Type.getMethodDescriptor(STRING, Type.getType(Locale.class));
82b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta
83b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta            @Override
84b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta            public boolean isNeeded(String owner, String name, String desc) {
85b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta                return JAVA_LOCALE_CLASS.equals(owner) && "()Ljava/lang/String;".equals(desc) &&
86b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta                        ("toLanguageTag".equals(name) || "getScript".equals(name));
87b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta            }
88b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta
89b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta            @Override
9017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            public void replace(MethodInformation mi) {
9117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                assert isNeeded(mi.owner, mi.name, mi.desc);
9217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                mi.opcode = Opcodes.INVOKESTATIC;
9317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                mi.owner = ANDROID_LOCALE_CLASS;
9417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                mi.desc = LOCALE_TO_STRING;
95b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta            }
96b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta        });
97b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta
98b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta        // Case 3: java.util.Locale.adjustLanguageCode() or java.util.Locale.forLanguageTag()
99b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta        METHOD_REPLACERS.add(new MethodReplacer() {
100b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta
101b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta            private final String STRING_TO_STRING = Type.getMethodDescriptor(STRING, STRING);
102b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta            private final String STRING_TO_LOCALE = Type.getMethodDescriptor(
103b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta                    Type.getType(Locale.class), STRING);
104b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta
1055cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            @Override
1065cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            public boolean isNeeded(String owner, String name, String desc) {
107b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta                return JAVA_LOCALE_CLASS.equals(owner) &&
108b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta                        ("adjustLanguageCode".equals(name) && desc.equals(STRING_TO_STRING) ||
109b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta                        "forLanguageTag".equals(name) && desc.equals(STRING_TO_LOCALE));
1105cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            }
1115cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta
1125cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            @Override
11317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            public void replace(MethodInformation mi) {
11417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                assert isNeeded(mi.owner, mi.name, mi.desc);
11517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                mi.owner = ANDROID_LOCALE_CLASS;
11617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            }
11717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta        });
11817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta
11917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta        // Case 4: java.lang.System.log?()
12017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta        METHOD_REPLACERS.add(new MethodReplacer() {
12117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            @Override
12217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            public boolean isNeeded(String owner, String name, String desc) {
12317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                return JAVA_LANG_SYSTEM.equals(owner) && name.length() == 4
12417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                        && name.startsWith("log");
12517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            }
12617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta
12717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            @Override
12817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            public void replace(MethodInformation mi) {
12917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                assert isNeeded(mi.owner, mi.name, mi.desc);
13017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                assert mi.desc.equals("(Ljava/lang/String;Ljava/lang/Throwable;)V")
13117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                        || mi.desc.equals("(Ljava/lang/String;)V");
13217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                mi.name = "log";
13317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                mi.owner = Type.getInternalName(System_Delegate.class);
1345cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            }
1355cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta        });
1361330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta
1371330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta        // Case 5: java.util.LinkedHashMap.eldest()
1381330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta        METHOD_REPLACERS.add(new MethodReplacer() {
1391330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta
1401330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta            private final String VOID_TO_MAP_ENTRY =
1411330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta                    Type.getMethodDescriptor(Type.getType(Map.Entry.class));
1421330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta            private final String LINKED_HASH_MAP = Type.getInternalName(LinkedHashMap.class);
1431330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta
1441330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta            @Override
1451330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta            public boolean isNeeded(String owner, String name, String desc) {
1461330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta                return LINKED_HASH_MAP.equals(owner) &&
1471330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta                        "eldest".equals(name) &&
1481330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta                        VOID_TO_MAP_ENTRY.equals(desc);
1491330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta            }
1501330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta
1511330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta            @Override
1521330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta            public void replace(MethodInformation mi) {
1531330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta                assert isNeeded(mi.owner, mi.name, mi.desc);
1541330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta                mi.opcode = Opcodes.INVOKESTATIC;
1551330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta                mi.owner = Type.getInternalName(LinkedHashMap_Delegate.class);
1561330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta                mi.desc = Type.getMethodDescriptor(
1571330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta                        Type.getType(Map.Entry.class), Type.getType(LinkedHashMap.class));
1581330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta            }
1591330f79f95fd14b53c393402fbcbf7b7bbdcbc60Deepanshu Gupta        });
1605cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta    }
1615cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta
1625cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta    public static boolean isReplacementNeeded(String owner, String name, String desc) {
1635cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta        for (MethodReplacer replacer : METHOD_REPLACERS) {
1645cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            if (replacer.isNeeded(owner, name, desc)) {
1655cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta                return true;
1665cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            }
1675cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta        }
1685cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta        return false;
1695cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta    }
1705cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta
1711160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta    public ReplaceMethodCallsAdapter(ClassVisitor cv) {
1721160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta        super(Opcodes.ASM4, cv);
1731160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta    }
1741160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta
1751160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta    @Override
1761160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta    public MethodVisitor visitMethod(int access, String name, String desc, String signature,
1771160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta            String[] exceptions) {
1781160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta        return new MyMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions));
1791160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta    }
1801160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta
1811160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta    private class MyMethodVisitor extends MethodVisitor {
1821160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta
1831160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta        public MyMethodVisitor(MethodVisitor mv) {
1841160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta            super(Opcodes.ASM4, mv);
1851160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta        }
1861160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta
1871160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta        @Override
1881160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta        public void visitMethodInsn(int opcode, String owner, String name, String desc) {
1895cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta            for (MethodReplacer replacer : METHOD_REPLACERS) {
1905cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta                if (replacer.isNeeded(owner, name, desc)) {
19117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                    MethodInformation mi = new MethodInformation(opcode, owner, name, desc);
19217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                    replacer.replace(mi);
19317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                    opcode = mi.opcode;
19417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                    owner = mi.owner;
19517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                    name = mi.name;
19617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta                    desc = mi.desc;
1975cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta                    break;
198e1960cc0b541cda93db94de5bef42dff922b9ec3Deepanshu Gupta                }
1991160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta            }
2001160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta            super.visitMethodInsn(opcode, owner, name, desc);
2011160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta        }
2021160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta    }
2035cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta
20417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta    private static class MethodInformation {
20517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta        public int opcode;
20617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta        public String owner;
20717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta        public String name;
20817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta        public String desc;
20917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta
21017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta        public MethodInformation(int opcode, String owner, String name, String desc) {
21117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            this.opcode = opcode;
21217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            this.owner = owner;
21317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            this.name = name;
21417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta            this.desc = desc;
21517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta        }
21617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta    }
21717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta
2185cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta    private interface MethodReplacer {
2195cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta        public boolean isNeeded(String owner, String name, String desc);
2205cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta
2215cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta        /**
22217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta         * Updates the MethodInformation with the new values of the method attributes -
223b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta         * opcode, owner, name and desc.
224b80e42f93ff26984c410da0235dd10f463e5722aDeepanshu Gupta         *
2255cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta         */
22617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta        public void replace(MethodInformation mi);
2275cd9dde5a2a77c5095f985186d8f03147fd22870Deepanshu Gupta    }
2281160e6d2f7018117b0c29a7e2adba9ece36faec1Deepanshu Gupta}
229