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