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