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