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