Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2016 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 package android.signature.cts;
     17 
     18 import android.signature.cts.JDiffClassDescription.JDiffConstructor;
     19 import android.signature.cts.JDiffClassDescription.JDiffField;
     20 import android.signature.cts.JDiffClassDescription.JDiffMethod;
     21 
     22 import java.lang.reflect.Modifier;
     23 
     24 import org.xmlpull.v1.XmlPullParser;
     25 
     26 /**
     27  * Helper methods and constants used for parsing the current api file.
     28  */
     29 public class CurrentApi {
     30 
     31     private CurrentApi() {}
     32 
     33     public static final String API_FILE_DIRECTORY = "/data/local/tmp/signature-test";
     34 
     35     public static final String CURRENT_API_FILE =
     36             API_FILE_DIRECTORY + "/current.api";
     37     public static final String SYSTEM_CURRENT_API_FILE =
     38             API_FILE_DIRECTORY + "/system-current.api";
     39     public static final String SYSTEM_REMOVED_API_FILE =
     40             API_FILE_DIRECTORY + "/system-removed.api";
     41 
     42     static final String TAG_ROOT = "api";
     43     static final String TAG_PACKAGE = "package";
     44     static final String TAG_CLASS = "class";
     45     static final String TAG_INTERFACE = "interface";
     46     static final String TAG_IMPLEMENTS = "implements";
     47     static final String TAG_CONSTRUCTOR = "constructor";
     48     static final String TAG_METHOD = "method";
     49     static final String TAG_PARAM = "parameter";
     50     static final String TAG_EXCEPTION = "exception";
     51     static final String TAG_FIELD = "field";
     52 
     53     private static final String MODIFIER_ABSTRACT = "abstract";
     54     private static final String MODIFIER_FINAL = "final";
     55     private static final String MODIFIER_NATIVE = "native";
     56     private static final String MODIFIER_PRIVATE = "private";
     57     private static final String MODIFIER_PROTECTED = "protected";
     58     private static final String MODIFIER_PUBLIC = "public";
     59     private static final String MODIFIER_STATIC = "static";
     60     private static final String MODIFIER_SYNCHRONIZED = "synchronized";
     61     private static final String MODIFIER_TRANSIENT = "transient";
     62     private static final String MODIFIER_VOLATILE = "volatile";
     63     private static final String MODIFIER_VISIBILITY = "visibility";
     64 
     65     static final String ATTRIBUTE_NAME = "name";
     66     private static final String ATTRIBUTE_VALUE = "value";
     67     private static final String ATTRIBUTE_EXTENDS = "extends";
     68     static final String ATTRIBUTE_TYPE = "type";
     69     private static final String ATTRIBUTE_RETURN = "return";
     70 
     71     /**
     72      * Load field information from xml to memory.
     73      *
     74      * @param className of the class being examined which will be shown in error messages
     75      * @param parser The XmlPullParser which carries the xml information.
     76      * @return the new field
     77      */
     78     static JDiffField loadFieldInfo(String className, XmlPullParser parser) {
     79         String fieldName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
     80         String fieldType = parser.getAttributeValue(null, ATTRIBUTE_TYPE);
     81         int modifier = jdiffModifierToReflectionFormat(className, parser);
     82         String value = parser.getAttributeValue(null, ATTRIBUTE_VALUE);
     83         return new JDiffField(fieldName, fieldType, modifier, value);
     84     }
     85 
     86     /**
     87      * Load method information from xml to memory.
     88      *
     89      * @param className of the class being examined which will be shown in error messages
     90      * @param parser The XmlPullParser which carries the xml information.
     91      * @return the newly loaded method.
     92      */
     93     static JDiffMethod loadMethodInfo(String className, XmlPullParser parser) {
     94         String methodName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
     95         String returnType = parser.getAttributeValue(null, ATTRIBUTE_RETURN);
     96         int modifier = jdiffModifierToReflectionFormat(className, parser);
     97         return new JDiffMethod(methodName, modifier, returnType);
     98     }
     99 
    100     /**
    101      * Load constructor information from xml to memory.
    102      *
    103      * @param parser The XmlPullParser which carries the xml information.
    104      * @param currentClass the current class being loaded.
    105      * @return the new constructor
    106      */
    107     static JDiffConstructor loadConstructorInfo(
    108             XmlPullParser parser, JDiffClassDescription currentClass) {
    109         String name = currentClass.getClassName();
    110         int modifier = jdiffModifierToReflectionFormat(name, parser);
    111         return new JDiffConstructor(name, modifier);
    112     }
    113 
    114     /**
    115      * Load class or interface information to memory.
    116      *
    117      * @param parser The XmlPullParser which carries the xml information.
    118      * @param isInterface true if the current class is an interface, otherwise is false.
    119      * @param pkg the name of the java package this class can be found in.
    120      * @return the new class description.
    121      */
    122     static JDiffClassDescription loadClassInfo(
    123             XmlPullParser parser, boolean isInterface, String pkg) {
    124         String className = parser.getAttributeValue(null, ATTRIBUTE_NAME);
    125         JDiffClassDescription currentClass = new JDiffClassDescription(pkg, className);
    126 
    127         currentClass.setModifier(jdiffModifierToReflectionFormat(className, parser));
    128         currentClass.setType(isInterface ? JDiffClassDescription.JDiffType.INTERFACE :
    129                              JDiffClassDescription.JDiffType.CLASS);
    130         currentClass.setExtendsClass(parser.getAttributeValue(null, ATTRIBUTE_EXTENDS));
    131         return currentClass;
    132     }
    133 
    134     /**
    135      * Convert string modifier to int modifier.
    136      *
    137      * @param name of the class/method/field being examined which will be shown in error messages
    138      * @param key modifier name
    139      * @param value modifier value
    140      * @return converted modifier value
    141      */
    142     private static int modifierDescriptionToReflectedType(String name, String key, String value) {
    143         if (key.equals(MODIFIER_ABSTRACT)) {
    144             return value.equals("true") ? Modifier.ABSTRACT : 0;
    145         } else if (key.equals(MODIFIER_FINAL)) {
    146             return value.equals("true") ? Modifier.FINAL : 0;
    147         } else if (key.equals(MODIFIER_NATIVE)) {
    148             return value.equals("true") ? Modifier.NATIVE : 0;
    149         } else if (key.equals(MODIFIER_STATIC)) {
    150             return value.equals("true") ? Modifier.STATIC : 0;
    151         } else if (key.equals(MODIFIER_SYNCHRONIZED)) {
    152             return value.equals("true") ? Modifier.SYNCHRONIZED : 0;
    153         } else if (key.equals(MODIFIER_TRANSIENT)) {
    154             return value.equals("true") ? Modifier.TRANSIENT : 0;
    155         } else if (key.equals(MODIFIER_VOLATILE)) {
    156             return value.equals("true") ? Modifier.VOLATILE : 0;
    157         } else if (key.equals(MODIFIER_VISIBILITY)) {
    158             if (value.equals(MODIFIER_PRIVATE)) {
    159                 throw new RuntimeException("Private visibility found in API spec: " + name);
    160             } else if (value.equals(MODIFIER_PROTECTED)) {
    161                 return Modifier.PROTECTED;
    162             } else if (value.equals(MODIFIER_PUBLIC)) {
    163                 return Modifier.PUBLIC;
    164             } else if ("".equals(value)) {
    165                 // If the visibility is "", it means it has no modifier.
    166                 // which is package private. We should return 0 for this modifier.
    167                 return 0;
    168             } else {
    169                 throw new RuntimeException("Unknown modifier found in API spec: " + value);
    170             }
    171         }
    172         return 0;
    173     }
    174 
    175     /**
    176      * Transfer string modifier to int one.
    177      *
    178      * @param name of the class/method/field being examined which will be shown in error messages
    179      * @param parser XML resource parser
    180      * @return converted modifier
    181      */
    182     private static int jdiffModifierToReflectionFormat(String name, XmlPullParser parser){
    183         int modifier = 0;
    184         for (int i = 0;i < parser.getAttributeCount();i++) {
    185             modifier |= modifierDescriptionToReflectedType(name, parser.getAttributeName(i),
    186                     parser.getAttributeValue(i));
    187         }
    188         return modifier;
    189     }
    190 }
    191