ClassDefinition.java revision b6547e8fd56242dde90275d9b0ba6f3639083a61
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;
34
35import java.util.*;
36
37public class ClassDefinition {
38    private ClassDefItem classDefItem;
39    private ClassDataItem classDataItem;
40
41    private HashMap<Integer, AnnotationSetItem> methodAnnotations = new HashMap<Integer, AnnotationSetItem>();
42    private HashMap<Integer, AnnotationSetItem> fieldAnnotations = new HashMap<Integer, AnnotationSetItem>();
43
44    public ClassDefinition(ClassDefItem classDefItem) {
45        this.classDefItem = classDefItem;
46        this.classDataItem = classDefItem.getClassData();
47        buildAnnotationMaps();
48    }
49
50    private void buildAnnotationMaps() {
51        AnnotationDirectoryItem annotationDirectory = classDefItem.getAnnotationDirectory();
52        if (annotationDirectory == null) {
53            return;
54        }
55
56        List<AnnotationDirectoryItem.MethodAnnotation> methodAnnotationList = annotationDirectory.getMethodAnnotations();
57        if (methodAnnotations != null) {
58            for (AnnotationDirectoryItem.MethodAnnotation methodAnnotation: methodAnnotationList) {
59                methodAnnotations.put(methodAnnotation.getMethod().getIndex(), methodAnnotation.getAnnotationSet());
60            }
61        }
62
63        List<AnnotationDirectoryItem.FieldAnnotation> fieldAnnotationList = annotationDirectory.getFieldAnnotations();
64        if (fieldAnnotations != null) {
65            for (AnnotationDirectoryItem.FieldAnnotation fieldAnnotation: fieldAnnotationList) {
66                fieldAnnotations.put(fieldAnnotation.getField().getIndex(), fieldAnnotation.getAnnotationSet());
67            }
68        }
69    }
70
71    public List<String> getAccessFlags() {
72        List<String> accessFlags = new ArrayList<String>();
73
74        for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForClass(classDefItem.getAccessFlags())) {
75            accessFlags.add(accessFlag.toString());
76        }
77
78        return accessFlags;
79    }
80
81    public String getClassType() {
82        return classDefItem.getClassType().getTypeDescriptor();
83    }
84
85    public String getSuperType() {
86        return classDefItem.getSuperclass().getTypeDescriptor();
87    }
88
89    public String getSourceFile() {
90        return classDefItem.getSourceFile();
91    }
92
93    public List<String> getInterfaces() {
94        List<String> interfaces = new ArrayList<String>();
95
96        List<TypeIdItem> interfaceList = classDefItem.getInterfaces();
97
98        if (interfaceList != null) {
99            for (TypeIdItem typeIdItem: interfaceList) {
100                interfaces.add(typeIdItem.getTypeDescriptor());
101            }
102        }
103
104        return interfaces;
105    }
106
107    public List<FieldDefinition> getStaticFields() {
108        List<FieldDefinition> staticFields = new ArrayList<FieldDefinition>();
109
110        if (classDataItem != null) {
111
112            EncodedArrayItem encodedStaticInitializers = classDefItem.getStaticInitializers();
113
114            List<EncodedValue> staticInitializers;
115            if (encodedStaticInitializers != null) {
116                staticInitializers = encodedStaticInitializers.getEncodedArray().getValues();
117            } else {
118                staticInitializers = new ArrayList<EncodedValue>();
119            }
120
121            int i=0;
122            for (ClassDataItem.EncodedField field: classDataItem.getStaticFields()) {
123                EncodedValue encodedValue = null;
124                if (i < staticInitializers.size()) {
125                    encodedValue = staticInitializers.get(i);
126                }
127                AnnotationSetItem annotationSet = fieldAnnotations.get(field.getField().getIndex());
128                staticFields.add(new FieldDefinition(field, encodedValue, annotationSet));
129                i++;
130            }
131        }
132        return staticFields;
133    }
134
135    public List<FieldDefinition> getInstanceFields() {
136        List<FieldDefinition> instanceFields = new ArrayList<FieldDefinition>();
137
138        if (classDataItem != null) {
139            for (ClassDataItem.EncodedField field: classDataItem.getInstanceFields()) {
140                AnnotationSetItem annotationSet = fieldAnnotations.get(field.getField().getIndex());
141                instanceFields.add(new FieldDefinition(field, annotationSet));
142            }
143        }
144
145        return instanceFields;
146    }
147
148    public List<MethodDefinition> getDirectMethods() {
149        List<MethodDefinition> directMethods = new ArrayList<MethodDefinition>();
150
151        if (classDataItem != null) {
152            for (ClassDataItem.EncodedMethod method: classDataItem.getDirectMethods()) {
153                AnnotationSetItem annotationSet = methodAnnotations.get(method.getMethod().getIndex());
154                directMethods.add(new MethodDefinition(method, annotationSet));
155            }
156        }
157
158        return directMethods;
159    }
160
161    public List<MethodDefinition> getVirtualMethods() {
162        List<MethodDefinition> virtualMethods = new ArrayList<MethodDefinition>();
163
164        if (classDataItem != null) {
165            for (ClassDataItem.EncodedMethod method: classDataItem.getVirtualMethods()) {
166                AnnotationSetItem annotationSet = methodAnnotations.get(method.getMethod().getIndex());
167                virtualMethods.add(new MethodDefinition(method, annotationSet));
168            }
169        }
170
171        return virtualMethods;
172    }
173
174    public List<AnnotationAdaptor> getAnnotations() {
175        AnnotationDirectoryItem annotationDirectory = classDefItem.getAnnotationDirectory();
176        if (annotationDirectory == null) {
177            return null;
178        }
179
180        AnnotationSetItem annotationSet = annotationDirectory.getClassAnnotations();
181        if (annotationSet == null) {
182            return null;
183        }
184
185        List<AnnotationAdaptor> annotationAdaptors = new ArrayList<AnnotationAdaptor>();
186
187        for (AnnotationItem annotationItem: annotationSet.getAnnotationItems()) {
188            annotationAdaptors.add(new AnnotationAdaptor(annotationItem));
189        }
190        return annotationAdaptors;
191    }
192}
193