1f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project/*
2f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
3f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project *
4f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * you may not use this file except in compliance with the License.
6f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * You may obtain a copy of the License at
7f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project *
8f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project *
10f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * See the License for the specific language governing permissions and
14f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * limitations under the License.
15f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project */
16f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
17f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectpackage dex.reader;
18f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
19f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.lang.reflect.Modifier;
20f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.util.HashMap;
21f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.util.HashSet;
22f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.util.LinkedList;
23f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.util.List;
24f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.util.Map;
25f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.util.Set;
26f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
27f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.reader.DexClassImpl.MethodAnnotation;
28f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.reader.DexClassImpl.ParameterAnnotation;
29f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.reader.DexFileReader.FieldIdItem;
30f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.reader.DexFileReader.MethodsIdItem;
31f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.reader.DexFileReader.ProtIdItem;
32f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.structure.DexAnnotation;
33f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.structure.DexClass;
34f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.structure.DexMethod;
35f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.structure.DexParameter;
36f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
37f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project/* package */final class DexMethodImpl implements DexMethod {
38f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
39f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private DexBuffer buffer;
40f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private MethodsIdItem methodsIdItem;
41f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private String[] stringPool;
42f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private int[] typeIds;
43f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private ProtIdItem protoIdItem;
44f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private List<DexParameter> parameters;
45f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private final int accessFlags;
46f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private final MethodAnnotation methodAnnotation;
47f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private Set<DexAnnotation> annotations;
48f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private final TypeFormatter formatter = new TypeFormatter();
49f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private final DexClass declaringClass;
50f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private final ParameterAnnotation parameterAnnotation;
51f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private Map<Integer, Integer> parameterIdToIndex;
52f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private final FieldIdItem[] fieldIdItems;
53f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
54f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public DexMethodImpl(DexBuffer buffer, DexClass declaringClass,
55f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            MethodsIdItem methodsIdItem, ProtIdItem protoIdItem,
56f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            int accessFlags, MethodAnnotation methodAnnotation,
57f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            ParameterAnnotation parameterAnnotation, String[] stringPool,
58f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            int[] typeIds, FieldIdItem[] fieldIdItems) {
59f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        this.buffer = buffer;
60f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        this.declaringClass = declaringClass;
61f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        this.methodsIdItem = methodsIdItem;
62f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        this.protoIdItem = protoIdItem;
63f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        this.accessFlags = accessFlags;
64f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        this.methodAnnotation = methodAnnotation;
65f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        this.parameterAnnotation = parameterAnnotation;
66f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        this.stringPool = stringPool;
67f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        this.typeIds = typeIds;
68f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        this.fieldIdItems = fieldIdItems;
69f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        parseAnnotations();
70f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        parseParameterAnnotations();
71f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
72f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
73f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private void parseParameterAnnotations() {
74f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        parameterIdToIndex = new HashMap<Integer, Integer>();
75f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        if (parameterAnnotation != null) {
76f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            buffer.setPosition(parameterAnnotation.annotationsOff);
77f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            int numberOfParameters = buffer.readUInt();
78f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            for (int i = 0; i < numberOfParameters; i++) {
79f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                parameterIdToIndex.put(i, buffer.readUInt());
80f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            }
81f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        }
82f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
83f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
84f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private void parseAnnotations() {
85f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        annotations = new HashSet<DexAnnotation>();
86f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        if (methodAnnotation != null) {
87f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            buffer.setPosition(methodAnnotation.annotationsOff);
88f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            final int size = buffer.readUInt();
89f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            for (int i = 0; i < size; i++) {
90f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                annotations.add(new DexAnnotationImpl(buffer.createCopy(),
91f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                        buffer.readUInt(), typeIds, stringPool, fieldIdItems));
92f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            }
93f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        }
94f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
95f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
96f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public String getName() {
97f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return stringPool[methodsIdItem.name_idx];
98f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
99f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
100f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public String getReturnType() {
101f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return stringPool[typeIds[protoIdItem.return_type_idx]];
102f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
103f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
104f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public synchronized List<DexParameter> getParameters() {
105f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        if (parameters == null) {
106f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            parameters = new LinkedList<DexParameter>();
107f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            if (protoIdItem.parameter_off != 0) {
108f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
109f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                buffer.setPosition(protoIdItem.parameter_off);
110f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                int size = buffer.readUInt();
111f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
112f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                int[] paramTypeIdx = new int[size];
113f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                for (int i = 0; i < size; i++) {
114f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                    paramTypeIdx[i] = buffer.readUShort();
115f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                }
116f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                for (int i = 0; i < paramTypeIdx.length; i++) {
117f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                    parameters.add(new DexParameterImpl(buffer.createCopy(),
118f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                            stringPool[typeIds[paramTypeIdx[i]]],
119f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                            parameterIdToIndex.get(i), typeIds, stringPool,
120f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                            fieldIdItems));
121f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                }
122f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            }
123f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        }
124f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return parameters;
125f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
126f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
127f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public int getModifiers() {
128f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return accessFlags;
129f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
130f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
131f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public Set<DexAnnotation> getAnnotations() {
132f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return annotations;
133f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
134f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
135f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public DexClass getDeclaringClass() {
136f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return declaringClass;
137f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
138f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
139f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    @Override
140f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public String toString() {
141f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        StringBuilder builder = new StringBuilder();
142f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        builder.append(formatter.formatAnnotations(getAnnotations()));
143f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        builder.append(Modifier.toString(getModifiers()));
144f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        builder.append(" ");
145f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        builder.append(formatter.format(getReturnType()));
146f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        builder.append(" ");
147f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        builder.append(getName());
148f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        builder.append("(");
149f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        List<DexParameter> parameters = getParameters();
150f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        for (DexParameter dexParameter : parameters) {
151f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            builder.append(formatter.formatAnnotations(dexParameter
152f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                    .getAnnotations()));
153f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            builder.append(formatter.format(dexParameter.getTypeName()));
154f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        }
155f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        builder.append(")");
156f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return builder.toString();
157f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
158f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project}
159