ReflectionClassDef.java revision c456c55c40d0731edb9913fae73f16b9d94ac45b
1/*
2 * Copyright 2013, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32package org.jf.dexlib2.analysis.reflection;
33
34import com.google.common.base.Function;
35import com.google.common.base.Predicate;
36import com.google.common.collect.ImmutableList;
37import com.google.common.collect.ImmutableSet;
38import com.google.common.collect.Iterators;
39import org.jf.dexlib2.analysis.reflection.util.ReflectionUtils;
40import org.jf.dexlib2.base.reference.BaseTypeReference;
41import org.jf.dexlib2.iface.Annotation;
42import org.jf.dexlib2.iface.ClassDef;
43import org.jf.dexlib2.iface.Field;
44import org.jf.dexlib2.iface.Method;
45
46import javax.annotation.Nonnull;
47import javax.annotation.Nullable;
48import java.lang.reflect.Constructor;
49import java.lang.reflect.Modifier;
50import java.util.AbstractSet;
51import java.util.Iterator;
52import java.util.List;
53import java.util.Set;
54
55/**
56 * Wraps a ClassDef around a class loaded in the current VM
57 *
58 * Only supports the basic information exposed by ClassProto
59 */
60public class ReflectionClassDef extends BaseTypeReference implements ClassDef {
61    private final Class cls;
62
63    public ReflectionClassDef(Class cls) {
64        this.cls = cls;
65    }
66
67    @Override public int getAccessFlags() {
68        // the java modifiers appear to be the same as the dex access flags
69        return cls.getModifiers();
70    }
71
72    @Nullable @Override public String getSuperclass() {
73        if (Modifier.isInterface(cls.getModifiers())) {
74            return "Ljava/lang/Object;";
75        }
76        Class superClass = cls.getSuperclass();
77        if (superClass == null) {
78            return null;
79        }
80        return ReflectionUtils.javaToDexName(superClass.getName());
81    }
82
83    @Nonnull @Override public List<String> getInterfaces() {
84        return ImmutableList.copyOf(Iterators.transform(Iterators.forArray(cls.getInterfaces()), new Function<Class, String>() {
85            @Nullable
86            @Override
87            public String apply(@Nullable Class input) {
88                if (input == null) {
89                    return null;
90                }
91                return ReflectionUtils.javaToDexName(input.getName());
92            }
93        }));
94    }
95
96    @Nullable @Override public String getSourceFile() {
97        return null;
98    }
99
100    @Nonnull @Override public Set<? extends Annotation> getAnnotations() {
101        return ImmutableSet.of();
102    }
103
104    @Nonnull @Override public Iterable<? extends Field> getStaticFields() {
105        return new Iterable<Field>() {
106            @Nonnull @Override public Iterator<Field> iterator() {
107                Iterator<java.lang.reflect.Field> staticFields = Iterators.filter(
108                        Iterators.forArray(cls.getDeclaredFields()),
109                        new Predicate<java.lang.reflect.Field>() {
110                            @Override public boolean apply(@Nullable java.lang.reflect.Field input) {
111                                return input!=null && Modifier.isStatic(input.getModifiers());
112                            }
113                        });
114
115                return Iterators.transform(staticFields,
116                        new Function<java.lang.reflect.Field, Field>() {
117                            @Nullable @Override public Field apply(@Nullable java.lang.reflect.Field input) {
118                                return new ReflectionField(input);
119                            }
120                        }
121                );
122            }
123        };
124    }
125
126    @Nonnull @Override public Iterable<? extends Field> getInstanceFields() {
127        return new Iterable<Field>() {
128            @Nonnull @Override public Iterator<Field> iterator() {
129                Iterator<java.lang.reflect.Field> staticFields = Iterators.filter(
130                        Iterators.forArray(cls.getDeclaredFields()),
131                        new Predicate<java.lang.reflect.Field>() {
132                            @Override public boolean apply(@Nullable java.lang.reflect.Field input) {
133                                return input!=null && !Modifier.isStatic(input.getModifiers());
134                            }
135                        });
136
137                return Iterators.transform(staticFields,
138                        new Function<java.lang.reflect.Field, Field>() {
139                            @Nullable @Override public Field apply(@Nullable java.lang.reflect.Field input) {
140                                return new ReflectionField(input);
141                            }
142                        }
143                );
144            }
145        };
146    }
147
148    @Nonnull @Override public Set<? extends Field> getFields() {
149        return new AbstractSet<Field>() {
150            @Nonnull @Override public Iterator<Field> iterator() {
151                return Iterators.transform(Iterators.forArray(cls.getDeclaredFields()),
152                        new Function<java.lang.reflect.Field, Field>() {
153                            @Nullable @Override public Field apply(@Nullable java.lang.reflect.Field input) {
154                                return new ReflectionField(input);
155                            }
156                        });
157            }
158
159            @Override public int size() {
160                return cls.getDeclaredFields().length;
161            }
162        };
163    }
164
165    private static final int DIRECT_MODIFIERS = Modifier.PRIVATE | Modifier.STATIC;
166    @Nonnull @Override public Iterable<? extends Method> getDirectMethods() {
167        return new Iterable<Method>() {
168            @Nonnull @Override public Iterator<Method> iterator() {
169                Iterator<Method> constructorIterator =
170                        Iterators.transform(Iterators.forArray(cls.getDeclaredConstructors()),
171                                new Function<Constructor, Method>() {
172                                    @Nullable @Override public Method apply(@Nullable Constructor input) {
173                                        return new ReflectionConstructor(input);
174                                    }
175                                });
176
177                Iterator<java.lang.reflect.Method> directMethods = Iterators.filter(
178                        Iterators.forArray(cls.getDeclaredMethods()),
179                        new Predicate<java.lang.reflect.Method>() {
180                            @Override public boolean apply(@Nullable java.lang.reflect.Method input) {
181                                return input != null && (input.getModifiers() & DIRECT_MODIFIERS) != 0;
182                            }
183                        });
184
185                Iterator<Method> methodIterator = Iterators.transform(directMethods,
186                        new Function<java.lang.reflect.Method, Method>() {
187                            @Nullable @Override public Method apply(@Nullable java.lang.reflect.Method input) {
188                                return new ReflectionMethod(input);
189                            }
190                        });
191                return Iterators.concat(constructorIterator, methodIterator);
192            }
193        };
194    }
195
196    @Nonnull @Override public Iterable<? extends Method> getVirtualMethods() {
197        return new Iterable<Method>() {
198            @Nonnull @Override public Iterator<Method> iterator() {
199                Iterator<java.lang.reflect.Method> directMethods = Iterators.filter(
200                        Iterators.forArray(cls.getDeclaredMethods()),
201                        new Predicate<java.lang.reflect.Method>() {
202                            @Override public boolean apply(@Nullable java.lang.reflect.Method input) {
203                                return input != null && (input.getModifiers() & DIRECT_MODIFIERS) == 0;
204                            }
205                        });
206
207                return Iterators.transform(directMethods,
208                        new Function<java.lang.reflect.Method, Method>() {
209                            @Nullable @Override public Method apply(@Nullable java.lang.reflect.Method input) {
210                                return new ReflectionMethod(input);
211                            }
212                        });
213            }
214        };
215    }
216
217    @Nonnull @Override public Set<? extends Method> getMethods() {
218        return new AbstractSet<Method>() {
219            @Nonnull @Override public Iterator<Method> iterator() {
220                Iterator<Method> constructorIterator =
221                        Iterators.transform(Iterators.forArray(cls.getDeclaredConstructors()),
222                                new Function<Constructor, Method>() {
223                                    @Nullable @Override public Method apply(@Nullable Constructor input) {
224                                        return new ReflectionConstructor(input);
225                                    }
226                                });
227
228                Iterator<Method> methodIterator =
229                        Iterators.transform(Iterators.forArray(cls.getDeclaredMethods()),
230                                new Function<java.lang.reflect.Method, Method>() {
231                                    @Nullable @Override public Method apply(@Nullable java.lang.reflect.Method input) {
232                                        return new ReflectionMethod(input);
233                                    }
234                                });
235                return Iterators.concat(constructorIterator, methodIterator);
236            }
237
238            @Override public int size() {
239                return cls.getDeclaredMethods().length + cls.getDeclaredConstructors().length;
240            }
241        };
242    }
243
244    @Nonnull @Override public String getType() {
245        return ReflectionUtils.javaToDexName(cls.getName());
246    }
247}
248