Home | History | Annotate | Download | only in reader
      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