Home | History | Annotate | Download | only in reflection
      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 
     32 package org.jf.dexlib2.analysis.reflection;
     33 
     34 import com.google.common.base.Function;
     35 import com.google.common.base.Predicate;
     36 import com.google.common.collect.ImmutableList;
     37 import com.google.common.collect.ImmutableSet;
     38 import com.google.common.collect.Iterators;
     39 import org.jf.dexlib2.analysis.reflection.util.ReflectionUtils;
     40 import org.jf.dexlib2.base.reference.BaseTypeReference;
     41 import org.jf.dexlib2.iface.Annotation;
     42 import org.jf.dexlib2.iface.ClassDef;
     43 import org.jf.dexlib2.iface.Field;
     44 import org.jf.dexlib2.iface.Method;
     45 
     46 import javax.annotation.Nonnull;
     47 import javax.annotation.Nullable;
     48 import java.lang.reflect.Constructor;
     49 import java.lang.reflect.Modifier;
     50 import java.util.AbstractSet;
     51 import java.util.Iterator;
     52 import java.util.List;
     53 import 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  */
     60 public 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