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