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 dex.structure.DexAnnotation;
     20 import dex.structure.DexClass;
     21 import dex.structure.DexField;
     22 import dex.structure.DexFile;
     23 import dex.structure.DexMethod;
     24 
     25 import java.util.ArrayList;
     26 import java.util.List;
     27 import java.util.Set;
     28 
     29 /**
     30  * <pre>
     31  * TypeDescriptor := 'V' | FieldTypeDescriptor
     32  * FieldTypeDescriptor := NonArrayFieldTypeDescriptor | ('[' * 1...255) NonArrayFieldTypeDescriptor
     33  * NonArrayFieldTypeDescriptor := 'Z' | 'B' | 'S' | 'C' | 'I' | 'J' | 'F' | 'D' | 'L' FullClassName ';'
     34  * </pre>
     35  */
     36 public final class TypeFormatter {
     37 
     38     /**
     39      * V void; only valid for return types Z boolean B byte S short C char I int
     40      * J long F float D double Lfully/qualified/Name; the class
     41      * fully.qualified.Name [descriptor array of descriptor, usable recursively
     42      * for arrays-of-arrays, though it is invalid to have more than 255
     43      * dimensions.
     44      */
     45     public String format(String typeName) {
     46         if (typeName.length() == 1) {
     47             switch (typeName.charAt(0)) {
     48             case 'V':
     49                 return "void";
     50             case 'Z':
     51                 return "boolean";
     52             case 'B':
     53                 return "byte";
     54             case 'S':
     55                 return "short";
     56             case 'C':
     57                 return "char";
     58             case 'I':
     59                 return "int";
     60             case 'J':
     61                 return "long";
     62             case 'F':
     63                 return "float";
     64             case 'D':
     65                 return "double";
     66             }
     67         } else {
     68             if (typeName.startsWith("L")) {
     69                 return typeName.substring(1, typeName.length() - 1).replace(
     70                         "/", "."); // remove 'L' and ';', replace '/' with '.'
     71             } else if (typeName.startsWith("[")) {
     72                 return format(typeName.substring(1)) + "[]";
     73             }
     74         }
     75         System.err.println("Strange type in formatter: " + typeName);
     76         return typeName;
     77     }
     78 
     79     public String format(List<String> typeNames) {
     80         List<String> types = new ArrayList<String>(typeNames.size());
     81         for (String type : typeNames) {
     82             types.add(format(type));
     83         }
     84         return format(types, ", ");
     85     }
     86 
     87     public String formatAnnotations(Set<DexAnnotation> annotations) {
     88         return format(new ArrayList<DexAnnotation>(annotations), "\n") + "\n";
     89     }
     90 
     91     private String format(List<?> elements, String separator) {
     92         StringBuilder builder = new StringBuilder();
     93         boolean first = true;
     94         for (Object element : elements) {
     95             if (!first) {
     96                 builder.append(separator);
     97             }
     98             builder.append(element.toString());
     99             first = false;
    100         }
    101         return builder.toString();
    102     }
    103 
    104 
    105     public String formatDexFile(DexFile file) {
    106         StringBuilder builder = new StringBuilder();
    107         builder.append("----------------DEX_FILE--------------\n\n");
    108         builder.append("Filename: ").append(file.getName());
    109         builder.append("\n-----------DEFINED_CLASSES------------\n\n");
    110         for (DexClass dexClass : file.getDefinedClasses()) {
    111             builder.append("\n________________CLASS________________\n\n");
    112             builder.append(dexClass);
    113             builder.append("\n\n----------------FIELDS----------------\n");
    114             for (DexField field : dexClass.getFields()) {
    115                 builder.append(field).append("\n");
    116             }
    117             builder.append("----------------METHODS----------------\n");
    118             for (DexMethod method : dexClass.getMethods()) {
    119                 builder.append(method).append("\n");
    120             }
    121         }
    122         return builder.toString();
    123     }
    124 }
    125