ClassDefinition.java revision 29f49465ca358613486bd6bc61a1b9a5fa3bd1c1
1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2009 Ben Gruver
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29package org.jf.baksmali.Adaptors;
30
31import org.jf.dexlib.EncodedValue.EncodedValue;
32import org.jf.dexlib.*;
33import org.jf.dexlib.Util.AccessFlags;
34import org.jf.dexlib.Util.SparseArray;
35import org.antlr.stringtemplate.StringTemplate;
36import org.antlr.stringtemplate.StringTemplateGroup;
37
38import java.util.*;
39
40public class ClassDefinition {
41    private StringTemplateGroup stg;
42    private ClassDefItem classDefItem;
43    private ClassDataItem classDataItem;
44
45    private SparseArray<AnnotationSetItem> methodAnnotationsMap;
46    private SparseArray<AnnotationSetItem> fieldAnnotationsMap;
47    private SparseArray<AnnotationSetRefList> parameterAnnotationsMap;
48
49    public ClassDefinition(StringTemplateGroup stg, ClassDefItem classDefItem) {
50        this.stg = stg;
51        this.classDefItem = classDefItem;
52        this.classDataItem = classDefItem.getClassData();
53        buildAnnotationMaps();
54    }
55
56    public StringTemplate makeTemplate() {
57        StringTemplate template = stg.getInstanceOf("smaliFile");
58
59        template.setAttribute("AccessFlags", getAccessFlags());
60        template.setAttribute("ClassType", classDefItem.getClassType().getTypeDescriptor());
61        template.setAttribute("SuperType", getSuperType());
62        template.setAttribute("SourceFile", getSourceFile());
63        template.setAttribute("Interfaces", getInterfaces());
64        template.setAttribute("Annotations", getAnnotations());
65        template.setAttribute("StaticFields", getStaticFields());
66        template.setAttribute("InstanceFields", getInstanceFields());
67        template.setAttribute("DirectMethods", getDirectMethods());
68        template.setAttribute("VirtualMethods", getVirtualMethods());
69
70        return template;
71    }
72
73    private void buildAnnotationMaps() {
74        AnnotationDirectoryItem annotationDirectory = classDefItem.getAnnotations();
75        if (annotationDirectory == null) {
76            return;
77        }
78
79        methodAnnotationsMap = new SparseArray<AnnotationSetItem>(annotationDirectory.getMethodAnnotationCount());
80        annotationDirectory.iterateMethodAnnotations(new AnnotationDirectoryItem.MethodAnnotationIteratorDelegate() {
81            public void processMethodAnnotations(MethodIdItem method, AnnotationSetItem methodAnnotations) {
82                methodAnnotationsMap.put(method.getIndex(), methodAnnotations);
83            }
84        });
85
86        fieldAnnotationsMap = new SparseArray<AnnotationSetItem>(annotationDirectory.getFieldAnnotationCount());
87        annotationDirectory.iterateFieldAnnotations(new AnnotationDirectoryItem.FieldAnnotationIteratorDelegate() {
88            public void processFieldAnnotations(FieldIdItem field, AnnotationSetItem fieldAnnotations) {
89                fieldAnnotationsMap.put(field.getIndex(), fieldAnnotations);
90            }
91        });
92
93        parameterAnnotationsMap = new SparseArray<AnnotationSetRefList>(
94                annotationDirectory.getParameterAnnotationCount());
95        annotationDirectory.iterateParameterAnnotations(
96          new AnnotationDirectoryItem.ParameterAnnotationIteratorDelegate() {
97            public void processParameterAnnotations(MethodIdItem method, AnnotationSetRefList parameterAnnotations) {
98                parameterAnnotationsMap.put(method.getIndex(), parameterAnnotations);
99            }
100        });
101    }
102
103    private List<String> getAccessFlags() {
104        List<String> accessFlags = new ArrayList<String>();
105
106        for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForClass(classDefItem.getAccessFlags())) {
107            accessFlags.add(accessFlag.toString());
108        }
109
110        return accessFlags;
111    }
112
113
114    private String getSuperType() {
115        TypeIdItem superClass = classDefItem.getSuperclass();
116        if (superClass != null) {
117            return superClass.getTypeDescriptor();
118        }
119        return null;
120    }
121
122    private String getSourceFile() {
123        StringIdItem sourceFile = classDefItem.getSourceFile();
124
125        if (sourceFile == null) {
126            return null;
127        }
128        return classDefItem.getSourceFile().getStringValue();
129    }
130
131    private List<String> getInterfaces() {
132        List<String> interfaces = new ArrayList<String>();
133
134        TypeListItem interfaceList = classDefItem.getInterfaces();
135
136        if (interfaceList != null) {
137            for (TypeIdItem typeIdItem: interfaceList.getTypes()) {
138                interfaces.add(typeIdItem.getTypeDescriptor());
139            }
140        }
141
142        return interfaces;
143    }
144
145    private List<StringTemplate> getAnnotations() {
146        AnnotationDirectoryItem annotationDirectory = classDefItem.getAnnotations();
147        if (annotationDirectory == null) {
148            return null;
149        }
150
151        AnnotationSetItem annotationSet = annotationDirectory.getClassAnnotations();
152        if (annotationSet == null) {
153            return null;
154        }
155
156        List<StringTemplate> annotations = new ArrayList<StringTemplate>();
157
158        for (AnnotationItem annotationItem: annotationSet.getAnnotations()) {
159            annotations.add(AnnotationAdaptor.makeTemplate(stg, annotationItem));
160        }
161        return annotations;
162    }
163
164    private List<StringTemplate> getStaticFields() {
165        List<StringTemplate> staticFields = new ArrayList<StringTemplate>();
166
167        if (classDataItem != null) {
168            EncodedArrayItem encodedStaticInitializers = classDefItem.getStaticFieldInitializers();
169
170            EncodedValue[] staticInitializers;
171            if (encodedStaticInitializers != null) {
172                staticInitializers = encodedStaticInitializers.getEncodedArray().values;
173            } else {
174                staticInitializers = new EncodedValue[0];
175            }
176
177            int i=0;
178            for (ClassDataItem.EncodedField field: classDataItem.getStaticFields()) {
179                EncodedValue encodedValue = null;
180                if (i < staticInitializers.length) {
181                    encodedValue = staticInitializers[i];
182                }
183                AnnotationSetItem annotationSet = fieldAnnotationsMap.get(field.field.getIndex());
184
185                staticFields.add(FieldDefinition.createTemplate(stg, field, encodedValue, annotationSet));
186                i++;
187            }
188        }
189        return staticFields;
190    }
191
192    private List<StringTemplate> getInstanceFields() {
193        List<StringTemplate> instanceFields = new ArrayList<StringTemplate>();
194
195        if (classDataItem != null) {
196            for (ClassDataItem.EncodedField field: classDataItem.getInstanceFields()) {
197                AnnotationSetItem annotationSet = fieldAnnotationsMap.get(field.field.getIndex());
198                instanceFields.add(FieldDefinition.createTemplate(stg, field, annotationSet));
199            }
200        }
201
202        return instanceFields;
203    }
204
205    private List<StringTemplate> getDirectMethods() {
206        List<StringTemplate> directMethods = new ArrayList<StringTemplate>();
207
208        if (classDataItem != null) {
209            for (ClassDataItem.EncodedMethod method: classDataItem.getDirectMethods()) {
210                AnnotationSetItem annotationSet = methodAnnotationsMap.get(method.method.getIndex());
211                AnnotationSetRefList parameterAnnotationList = parameterAnnotationsMap.get(method.method.getIndex());
212                directMethods.add(MethodDefinition.makeTemplate(stg, method, annotationSet, parameterAnnotationList));
213            }
214        }
215
216        return directMethods;
217    }
218
219    private List<StringTemplate> getVirtualMethods() {
220        List<StringTemplate> virtualMethods = new ArrayList<StringTemplate>();
221
222        if (classDataItem != null) {
223            for (ClassDataItem.EncodedMethod method: classDataItem.getVirtualMethods()) {
224                AnnotationSetItem annotationSet = methodAnnotationsMap.get(method.method.getIndex());
225                AnnotationSetRefList parameterAnnotationList = parameterAnnotationsMap.get(method.method.getIndex());
226                virtualMethods.add(MethodDefinition.makeTemplate(stg, method, annotationSet, parameterAnnotationList));
227            }
228        }
229
230        return virtualMethods;
231    }
232}
233