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