1/* 2 * Copyright (C) 2008 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 17package com.android.dx.dex.file; 18 19import com.android.dx.rop.annotation.Annotation; 20import static com.android.dx.rop.annotation.AnnotationVisibility.SYSTEM; 21import com.android.dx.rop.annotation.NameValuePair; 22import com.android.dx.rop.cst.Constant; 23import com.android.dx.rop.cst.CstAnnotation; 24import com.android.dx.rop.cst.CstArray; 25import com.android.dx.rop.cst.CstInteger; 26import com.android.dx.rop.cst.CstKnownNull; 27import com.android.dx.rop.cst.CstMethodRef; 28import com.android.dx.rop.cst.CstString; 29import com.android.dx.rop.cst.CstType; 30import com.android.dx.rop.type.Type; 31import com.android.dx.rop.type.TypeList; 32import java.util.ArrayList; 33 34/** 35 * Utility class for dealing with annotations. 36 */ 37public final class AnnotationUtils { 38 39 /** 40 * Number of annotation types that dx may add in the dex file that were 41 * not defined in the translated class file. 42 */ 43 public static final int DALVIK_ANNOTATION_NUMBER = 7; 44 45 /** {@code non-null;} type for {@code AnnotationDefault} annotations */ 46 private static final CstType ANNOTATION_DEFAULT_TYPE = 47 CstType.intern(Type.intern("Ldalvik/annotation/AnnotationDefault;")); 48 49 /** {@code non-null;} type for {@code EnclosingClass} annotations */ 50 private static final CstType ENCLOSING_CLASS_TYPE = 51 CstType.intern(Type.intern("Ldalvik/annotation/EnclosingClass;")); 52 53 /** {@code non-null;} type for {@code EnclosingMethod} annotations */ 54 private static final CstType ENCLOSING_METHOD_TYPE = 55 CstType.intern(Type.intern("Ldalvik/annotation/EnclosingMethod;")); 56 57 /** {@code non-null;} type for {@code InnerClass} annotations */ 58 private static final CstType INNER_CLASS_TYPE = 59 CstType.intern(Type.intern("Ldalvik/annotation/InnerClass;")); 60 61 /** {@code non-null;} type for {@code MemberClasses} annotations */ 62 private static final CstType MEMBER_CLASSES_TYPE = 63 CstType.intern(Type.intern("Ldalvik/annotation/MemberClasses;")); 64 65 /** {@code non-null;} type for {@code Signature} annotations */ 66 private static final CstType SIGNATURE_TYPE = 67 CstType.intern(Type.intern("Ldalvik/annotation/Signature;")); 68 69 /** {@code non-null;} type for {@code Throws} annotations */ 70 private static final CstType THROWS_TYPE = 71 CstType.intern(Type.intern("Ldalvik/annotation/Throws;")); 72 73 /** {@code non-null;} the UTF-8 constant {@code "accessFlags"} */ 74 private static final CstString ACCESS_FLAGS_STRING = new CstString("accessFlags"); 75 76 /** {@code non-null;} the UTF-8 constant {@code "name"} */ 77 private static final CstString NAME_STRING = new CstString("name"); 78 79 /** {@code non-null;} the UTF-8 constant {@code "value"} */ 80 private static final CstString VALUE_STRING = new CstString("value"); 81 82 /** 83 * This class is uninstantiable. 84 */ 85 private AnnotationUtils() { 86 // This space intentionally left blank. 87 } 88 89 /** 90 * Constructs a standard {@code AnnotationDefault} annotation. 91 * 92 * @param defaults {@code non-null;} the defaults, itself as an annotation 93 * @return {@code non-null;} the constructed annotation 94 */ 95 public static Annotation makeAnnotationDefault(Annotation defaults) { 96 Annotation result = new Annotation(ANNOTATION_DEFAULT_TYPE, SYSTEM); 97 98 result.put(new NameValuePair(VALUE_STRING, new CstAnnotation(defaults))); 99 result.setImmutable(); 100 return result; 101 } 102 103 /** 104 * Constructs a standard {@code EnclosingClass} annotation. 105 * 106 * @param clazz {@code non-null;} the enclosing class 107 * @return {@code non-null;} the annotation 108 */ 109 public static Annotation makeEnclosingClass(CstType clazz) { 110 Annotation result = new Annotation(ENCLOSING_CLASS_TYPE, SYSTEM); 111 112 result.put(new NameValuePair(VALUE_STRING, clazz)); 113 result.setImmutable(); 114 return result; 115 } 116 117 /** 118 * Constructs a standard {@code EnclosingMethod} annotation. 119 * 120 * @param method {@code non-null;} the enclosing method 121 * @return {@code non-null;} the annotation 122 */ 123 public static Annotation makeEnclosingMethod(CstMethodRef method) { 124 Annotation result = new Annotation(ENCLOSING_METHOD_TYPE, SYSTEM); 125 126 result.put(new NameValuePair(VALUE_STRING, method)); 127 result.setImmutable(); 128 return result; 129 } 130 131 /** 132 * Constructs a standard {@code InnerClass} annotation. 133 * 134 * @param name {@code null-ok;} the original name of the class, or 135 * {@code null} to represent an anonymous class 136 * @param accessFlags the original access flags 137 * @return {@code non-null;} the annotation 138 */ 139 public static Annotation makeInnerClass(CstString name, int accessFlags) { 140 Annotation result = new Annotation(INNER_CLASS_TYPE, SYSTEM); 141 Constant nameCst = (name != null) ? name : CstKnownNull.THE_ONE; 142 143 result.put(new NameValuePair(NAME_STRING, nameCst)); 144 result.put(new NameValuePair(ACCESS_FLAGS_STRING, 145 CstInteger.make(accessFlags))); 146 result.setImmutable(); 147 return result; 148 } 149 150 /** 151 * Constructs a standard {@code MemberClasses} annotation. 152 * 153 * @param types {@code non-null;} the list of (the types of) the member classes 154 * @return {@code non-null;} the annotation 155 */ 156 public static Annotation makeMemberClasses(TypeList types) { 157 CstArray array = makeCstArray(types); 158 Annotation result = new Annotation(MEMBER_CLASSES_TYPE, SYSTEM); 159 result.put(new NameValuePair(VALUE_STRING, array)); 160 result.setImmutable(); 161 return result; 162 } 163 164 /** 165 * Constructs a standard {@code Signature} annotation. 166 * 167 * @param signature {@code non-null;} the signature string 168 * @return {@code non-null;} the annotation 169 */ 170 public static Annotation makeSignature(CstString signature) { 171 Annotation result = new Annotation(SIGNATURE_TYPE, SYSTEM); 172 173 /* 174 * Split the string into pieces that are likely to be common 175 * across many signatures and the rest of the file. 176 */ 177 178 String raw = signature.getString(); 179 int rawLength = raw.length(); 180 ArrayList<String> pieces = new ArrayList<String>(20); 181 182 for (int at = 0; at < rawLength; /*at*/) { 183 char c = raw.charAt(at); 184 int endAt = at + 1; 185 if (c == 'L') { 186 // Scan to ';' or '<'. Consume ';' but not '<'. 187 while (endAt < rawLength) { 188 c = raw.charAt(endAt); 189 if (c == ';') { 190 endAt++; 191 break; 192 } else if (c == '<') { 193 break; 194 } 195 endAt++; 196 } 197 } else { 198 // Scan to 'L' without consuming it. 199 while (endAt < rawLength) { 200 c = raw.charAt(endAt); 201 if (c == 'L') { 202 break; 203 } 204 endAt++; 205 } 206 } 207 208 pieces.add(raw.substring(at, endAt)); 209 at = endAt; 210 } 211 212 int size = pieces.size(); 213 CstArray.List list = new CstArray.List(size); 214 215 for (int i = 0; i < size; i++) { 216 list.set(i, new CstString(pieces.get(i))); 217 } 218 219 list.setImmutable(); 220 221 result.put(new NameValuePair(VALUE_STRING, new CstArray(list))); 222 result.setImmutable(); 223 return result; 224 } 225 226 /** 227 * Constructs a standard {@code Throws} annotation. 228 * 229 * @param types {@code non-null;} the list of thrown types 230 * @return {@code non-null;} the annotation 231 */ 232 public static Annotation makeThrows(TypeList types) { 233 CstArray array = makeCstArray(types); 234 Annotation result = new Annotation(THROWS_TYPE, SYSTEM); 235 result.put(new NameValuePair(VALUE_STRING, array)); 236 result.setImmutable(); 237 return result; 238 } 239 240 /** 241 * Converts a {@link TypeList} to a {@link CstArray}. 242 * 243 * @param types {@code non-null;} the type list 244 * @return {@code non-null;} the corresponding array constant 245 */ 246 private static CstArray makeCstArray(TypeList types) { 247 int size = types.size(); 248 CstArray.List list = new CstArray.List(size); 249 250 for (int i = 0; i < size; i++) { 251 list.set(i, CstType.intern(types.getType(i))); 252 } 253 254 list.setImmutable(); 255 return new CstArray(list); 256 } 257} 258