1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import java.lang.reflect.Constructor;
18 import java.lang.reflect.Field;
19 import java.lang.reflect.Method;
20 import java.lang.reflect.Modifier;
21 import java.util.Arrays;
22 
23 public class Reflection {
canDiscoverWithGetDeclaredField(Class<?> klass, String name)24   public static boolean canDiscoverWithGetDeclaredField(Class<?> klass, String name) {
25     try {
26       klass.getDeclaredField(name);
27       return true;
28     } catch (NoSuchFieldException ex) {
29       return false;
30     }
31   }
32 
canDiscoverWithGetDeclaredFields(Class<?> klass, String name)33   public static boolean canDiscoverWithGetDeclaredFields(Class<?> klass, String name) {
34     for (Field f : klass.getDeclaredFields()) {
35       if (f.getName().equals(name)) {
36         return true;
37       }
38     }
39     return false;
40   }
41 
canDiscoverWithGetField(Class<?> klass, String name)42   public static boolean canDiscoverWithGetField(Class<?> klass, String name) {
43     try {
44       klass.getField(name);
45       return true;
46     } catch (NoSuchFieldException ex) {
47       return false;
48     }
49   }
50 
canDiscoverWithGetFields(Class<?> klass, String name)51   public static boolean canDiscoverWithGetFields(Class<?> klass, String name) {
52     for (Field f : klass.getFields()) {
53       if (f.getName().equals(name)) {
54         return true;
55       }
56     }
57     return false;
58   }
59 
canGetField(Class<?> klass, String name)60   public static boolean canGetField(Class<?> klass, String name) {
61     try {
62       Field f = klass.getDeclaredField(name);
63       f.setAccessible(true);
64       f.getInt(Modifier.isStatic(f.getModifiers()) ? null : klass.newInstance());
65       return true;
66     } catch (Exception ex) {
67       ex.printStackTrace();
68       return false;
69     }
70   }
71 
canSetField(Class<?> klass, String name)72   public static boolean canSetField(Class<?> klass, String name) {
73     try {
74       Field f = klass.getDeclaredField(name);
75       f.setAccessible(true);
76       f.setInt(Modifier.isStatic(f.getModifiers()) ? null : klass.newInstance(), 42);
77       return true;
78     } catch (Exception ex) {
79       ex.printStackTrace();
80       return false;
81     }
82   }
83 
canDiscoverWithGetDeclaredMethod(Class<?> klass, String name)84   public static boolean canDiscoverWithGetDeclaredMethod(Class<?> klass, String name) {
85     try {
86       klass.getDeclaredMethod(name);
87       return true;
88     } catch (NoSuchMethodException ex) {
89       return false;
90     }
91   }
92 
canDiscoverWithGetDeclaredMethods(Class<?> klass, String name)93   public static boolean canDiscoverWithGetDeclaredMethods(Class<?> klass, String name) {
94     for (Method m : klass.getDeclaredMethods()) {
95       if (m.getName().equals(name)) {
96         return true;
97       }
98     }
99     return false;
100   }
101 
canDiscoverWithGetMethod(Class<?> klass, String name)102   public static boolean canDiscoverWithGetMethod(Class<?> klass, String name) {
103     try {
104       klass.getMethod(name);
105       return true;
106     } catch (NoSuchMethodException ex) {
107       return false;
108     }
109   }
110 
canDiscoverWithGetMethods(Class<?> klass, String name)111   public static boolean canDiscoverWithGetMethods(Class<?> klass, String name) {
112     for (Method m : klass.getMethods()) {
113       if (m.getName().equals(name)) {
114         return true;
115       }
116     }
117     return false;
118   }
119 
canInvokeMethod(Class<?> klass, String name)120   public static boolean canInvokeMethod(Class<?> klass, String name) {
121     try {
122       Method m = klass.getDeclaredMethod(name);
123       m.setAccessible(true);
124       m.invoke(klass.isInterface() ? null : klass.newInstance());
125       return true;
126     } catch (Exception ex) {
127       ex.printStackTrace();
128       return false;
129     }
130   }
131 
canDiscoverWithGetDeclaredConstructor(Class<?> klass, Class<?> args[])132   public static boolean canDiscoverWithGetDeclaredConstructor(Class<?> klass, Class<?> args[]) {
133     try {
134       klass.getDeclaredConstructor(args);
135       return true;
136     } catch (NoSuchMethodException ex) {
137       return false;
138     }
139   }
140 
canDiscoverWithGetDeclaredConstructors(Class<?> klass, Class<?> args[])141   public static boolean canDiscoverWithGetDeclaredConstructors(Class<?> klass, Class<?> args[]) {
142     for (Constructor c : klass.getDeclaredConstructors()) {
143       if (Arrays.equals(c.getParameterTypes(), args)) {
144         return true;
145       }
146     }
147     return false;
148   }
149 
canDiscoverWithGetConstructor(Class<?> klass, Class<?> args[])150   public static boolean canDiscoverWithGetConstructor(Class<?> klass, Class<?> args[]) {
151     try {
152       klass.getConstructor(args);
153       return true;
154     } catch (NoSuchMethodException ex) {
155       return false;
156     }
157   }
158 
canDiscoverWithGetConstructors(Class<?> klass, Class<?> args[])159   public static boolean canDiscoverWithGetConstructors(Class<?> klass, Class<?> args[]) {
160     for (Constructor c : klass.getConstructors()) {
161       if (Arrays.equals(c.getParameterTypes(), args)) {
162         return true;
163       }
164     }
165     return false;
166   }
167 
canInvokeConstructor(Class<?> klass, Class<?> args[], Object[] initargs)168   public static boolean canInvokeConstructor(Class<?> klass, Class<?> args[], Object[] initargs) {
169     try {
170       Constructor c = klass.getDeclaredConstructor(args);
171       c.setAccessible(true);
172       c.newInstance(initargs);
173       return true;
174     } catch (Exception ex) {
175       ex.printStackTrace();
176       return false;
177     }
178   }
179 
canUseNewInstance(Class<?> klass)180   public static boolean canUseNewInstance(Class<?> klass) throws IllegalAccessException {
181     try {
182       klass.newInstance();
183       return true;
184     } catch (InstantiationException ex) {
185       return false;
186     }
187   }
188 
getHiddenApiAccessFlags()189   private static native int getHiddenApiAccessFlags();
190 
canObserveFieldHiddenAccessFlags(Class<?> klass, String name)191   public static boolean canObserveFieldHiddenAccessFlags(Class<?> klass, String name)
192       throws Exception {
193     return (klass.getDeclaredField(name).getModifiers() & getHiddenApiAccessFlags()) != 0;
194   }
195 
canObserveMethodHiddenAccessFlags(Class<?> klass, String name)196   public static boolean canObserveMethodHiddenAccessFlags(Class<?> klass, String name)
197       throws Exception {
198     return (klass.getDeclaredMethod(name).getModifiers() & getHiddenApiAccessFlags()) != 0;
199   }
200 
canObserveConstructorHiddenAccessFlags(Class<?> klass, Class<?> args[])201   public static boolean canObserveConstructorHiddenAccessFlags(Class<?> klass, Class<?> args[])
202       throws Exception {
203     return (klass.getConstructor(args).getModifiers() & getHiddenApiAccessFlags()) != 0;
204   }
205 }
206