ClassDefinition.java revision 7885a819a0dc52568fedd60f7d8d0f0a9ca352e9
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.antlr.stringtemplate.StringTemplate;
35import org.antlr.stringtemplate.StringTemplateGroup;
36
37import java.util.*;
38
39public class ClassDefinition {
40    private StringTemplateGroup stg;
41    private ClassDefItem classDefItem;
42    private ClassDataItem classDataItem;
43
44    private HashMap<Integer, AnnotationSetItem> methodAnnotationsMap = new HashMap<Integer, AnnotationSetItem>();
45    private HashMap<Integer, AnnotationSetItem> fieldAnnotationsMap = new HashMap<Integer, AnnotationSetItem>();
46    private HashMap<Integer, AnnotationSetRefList> parameterAnnotationsMap = new HashMap<Integer, AnnotationSetRefList>();
47
48    public ClassDefinition(StringTemplateGroup stg, ClassDefItem classDefItem) {
49        this.stg = stg;
50        this.classDefItem = classDefItem;
51        this.classDataItem = classDefItem.getClassData();
52        buildAnnotationMaps();
53    }
54
55    public StringTemplate makeTemplate() {
56        StringTemplate template = stg.getInstanceOf("smaliFile");
57
58        template.setAttribute("AccessFlags", getAccessFlags());
59        template.setAttribute("ClassType", classDefItem.getClassType().getTypeDescriptor());
60        template.setAttribute("SuperType", getSuperType());
61        template.setAttribute("SourceFile", getSourceFile());
62        template.setAttribute("Interfaces", getInterfaces());
63        template.setAttribute("Annotations", getAnnotations());
64        template.setAttribute("StaticFields", getStaticFields());
65        template.setAttribute("InstanceFields", getInstanceFields());
66        template.setAttribute("DirectMethods", getDirectMethods());
67        template.setAttribute("VirtualMethods", getVirtualMethods());
68
69        return template;
70    }
71
72    private void buildAnnotationMaps() {
73        AnnotationDirectoryItem annotationDirectory = classDefItem.getAnnotations();
74        if (annotationDirectory == null) {
75            return;
76        }
77
78        annotationDirectory.iterateMethodAnnotations(new AnnotationDirectoryItem.MethodAnnotationIteratorDelegate() {
79            public void processMethodAnnotations(MethodIdItem method, AnnotationSetItem methodAnnotations) {
80                methodAnnotationsMap.put(method.getIndex(), methodAnnotations);
81            }
82        });
83
84        annotationDirectory.iterateFieldAnnotations(new AnnotationDirectoryItem.FieldAnnotationIteratorDelegate() {
85            public void processFieldAnnotations(FieldIdItem field, AnnotationSetItem fieldAnnotations) {
86                fieldAnnotationsMap.put(field.getIndex(), fieldAnnotations);
87            }
88        });
89
90        annotationDirectory.iteratParameterAnnotations(
91        new AnnotationDirectoryItem.ParameterAnnotationIteratorDelegate() {
92            public void processParameterAnnotations(MethodIdItem method, AnnotationSetRefList parameterAnnotations) {
93                parameterAnnotationsMap.put(method.getIndex(), parameterAnnotations);
94            }
95        });
96    }
97
98    private List<String> getAccessFlags() {
99        List<String> accessFlags = new ArrayList<String>();
100
101        for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForClass(classDefItem.getAccessFlags())) {
102            accessFlags.add(accessFlag.toString());
103        }
104
105        return accessFlags;
106    }
107
108
109    private String getSuperType() {
110        TypeIdItem superClass = classDefItem.getSuperclass();
111        if (superClass != null) {
112            return superClass.getTypeDescriptor();
113        }
114        return null;
115    }
116
117    private String getSourceFile() {
118        StringIdItem sourceFile = classDefItem.getSourceFile();
119
120        if (sourceFile == null) {
121            return null;
122        }
123        return classDefItem.getSourceFile().getStringValue();
124    }
125
126    private List<String> getInterfaces() {
127        List<String> interfaces = new ArrayList<String>();
128
129        TypeListItem interfaceList = classDefItem.getInterfaces();
130
131        if (interfaceList != null) {
132            for (TypeIdItem typeIdItem: interfaceList.getTypes()) {
133                interfaces.add(typeIdItem.getTypeDescriptor());
134            }
135        }
136
137        return interfaces;
138    }
139
140    private List<StringTemplate> getAnnotations() {
141        AnnotationDirectoryItem annotationDirectory = classDefItem.getAnnotations();
142        if (annotationDirectory == null) {
143            return null;
144        }
145
146        AnnotationSetItem annotationSet = annotationDirectory.getClassAnnotations();
147        if (annotationSet == null) {
148            return null;
149        }
150
151        List<StringTemplate> annotations = new ArrayList<StringTemplate>();
152
153        for (AnnotationItem annotationItem: annotationSet.getAnnotations()) {
154            annotations.add(AnnotationAdaptor.makeTemplate(stg, annotationItem));
155        }
156        return annotations;
157    }
158
159    private List<StringTemplate> getStaticFields() {
160        List<StringTemplate> staticFields = new ArrayList<StringTemplate>();
161
162        if (classDataItem != null) {
163            EncodedArrayItem encodedStaticInitializers = classDefItem.getStaticFieldInitializers();
164
165            EncodedValue[] staticInitializers;
166            if (encodedStaticInitializers != null) {
167                staticInitializers = encodedStaticInitializers.getEncodedArray().values;
168            } else {
169                staticInitializers = new EncodedValue[0];
170            }
171
172            int i=0;
173            for (ClassDataItem.EncodedField field: classDataItem.getStaticFields()) {
174                EncodedValue encodedValue = null;
175                if (i < staticInitializers.length) {
176                    encodedValue = staticInitializers[i];
177                }
178                AnnotationSetItem annotationSet = fieldAnnotationsMap.get(field.field.getIndex());
179
180                staticFields.add(FieldDefinition.createTemplate(stg, field, encodedValue, annotationSet));
181                i++;
182            }
183        }
184        return staticFields;
185    }
186
187    private List<StringTemplate> getInstanceFields() {
188        List<StringTemplate> instanceFields = new ArrayList<StringTemplate>();
189
190        if (classDataItem != null) {
191            for (ClassDataItem.EncodedField field: classDataItem.getInstanceFields()) {
192                AnnotationSetItem annotationSet = fieldAnnotationsMap.get(field.field.getIndex());
193                instanceFields.add(FieldDefinition.createTemplate(stg, field, annotationSet));
194            }
195        }
196
197        return instanceFields;
198    }
199
200    private List<StringTemplate> getDirectMethods() {
201        List<StringTemplate> directMethods = new ArrayList<StringTemplate>();
202
203        if (classDataItem != null) {
204            for (ClassDataItem.EncodedMethod method: classDataItem.getDirectMethods()) {
205                AnnotationSetItem annotationSet = methodAnnotationsMap.get(method.method.getIndex());
206                AnnotationSetRefList parameterAnnotationList = parameterAnnotationsMap.get(method.method.getIndex());
207                directMethods.add(MethodDefinition.makeTemplate(stg, method, annotationSet, parameterAnnotationList));
208            }
209        }
210
211        return directMethods;
212    }
213
214    private List<StringTemplate> getVirtualMethods() {
215        List<StringTemplate> virtualMethods = new ArrayList<StringTemplate>();
216
217        if (classDataItem != null) {
218            for (ClassDataItem.EncodedMethod method: classDataItem.getVirtualMethods()) {
219                AnnotationSetItem annotationSet = methodAnnotationsMap.get(method.method.getIndex());
220                AnnotationSetRefList parameterAnnotationList = parameterAnnotationsMap.get(method.method.getIndex());
221                virtualMethods.add(MethodDefinition.makeTemplate(stg, method, annotationSet, parameterAnnotationList));
222            }
223        }
224
225        return virtualMethods;
226    }
227}
228