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