blob: 173b9afeeb43baaf87c523aba218609c69aedae6 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
public class Reflection {
public static boolean canDiscoverWithGetDeclaredField(Class<?> klass, String name) {
try {
klass.getDeclaredField(name);
return true;
} catch (NoSuchFieldException ex) {
return false;
}
}
public static boolean canDiscoverWithGetDeclaredFields(Class<?> klass, String name) {
for (Field f : klass.getDeclaredFields()) {
if (f.getName().equals(name)) {
return true;
}
}
return false;
}
public static boolean canDiscoverWithGetField(Class<?> klass, String name) {
try {
klass.getField(name);
return true;
} catch (NoSuchFieldException ex) {
return false;
}
}
public static boolean canDiscoverWithGetFields(Class<?> klass, String name) {
for (Field f : klass.getFields()) {
if (f.getName().equals(name)) {
return true;
}
}
return false;
}
public static boolean canGetField(Class<?> klass, String name) {
try {
Field f = klass.getDeclaredField(name);
f.setAccessible(true);
f.getInt(Modifier.isStatic(f.getModifiers()) ? null : klass.newInstance());
return true;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
public static boolean canSetField(Class<?> klass, String name) {
try {
Field f = klass.getDeclaredField(name);
f.setAccessible(true);
f.setInt(Modifier.isStatic(f.getModifiers()) ? null : klass.newInstance(), 42);
return true;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
public static boolean canDiscoverWithGetDeclaredMethod(Class<?> klass, String name) {
try {
klass.getDeclaredMethod(name);
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public static boolean canDiscoverWithGetDeclaredMethods(Class<?> klass, String name) {
for (Method m : klass.getDeclaredMethods()) {
if (m.getName().equals(name)) {
return true;
}
}
return false;
}
public static boolean canDiscoverWithGetMethod(Class<?> klass, String name) {
try {
klass.getMethod(name);
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public static boolean canDiscoverWithGetMethods(Class<?> klass, String name) {
for (Method m : klass.getMethods()) {
if (m.getName().equals(name)) {
return true;
}
}
return false;
}
public static boolean canInvokeMethod(Class<?> klass, String name) {
try {
Method m = klass.getDeclaredMethod(name);
m.setAccessible(true);
m.invoke(klass.isInterface() ? null : klass.newInstance());
return true;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
public static boolean canDiscoverWithGetDeclaredConstructor(Class<?> klass, Class<?> args[]) {
try {
klass.getDeclaredConstructor(args);
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public static boolean canDiscoverWithGetDeclaredConstructors(Class<?> klass, Class<?> args[]) {
for (Constructor c : klass.getDeclaredConstructors()) {
if (Arrays.equals(c.getParameterTypes(), args)) {
return true;
}
}
return false;
}
public static boolean canDiscoverWithGetConstructor(Class<?> klass, Class<?> args[]) {
try {
klass.getConstructor(args);
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public static boolean canDiscoverWithGetConstructors(Class<?> klass, Class<?> args[]) {
for (Constructor c : klass.getConstructors()) {
if (Arrays.equals(c.getParameterTypes(), args)) {
return true;
}
}
return false;
}
public static boolean canInvokeConstructor(Class<?> klass, Class<?> args[], Object[] initargs) {
try {
Constructor c = klass.getDeclaredConstructor(args);
c.setAccessible(true);
c.newInstance(initargs);
return true;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
public static boolean canUseNewInstance(Class<?> klass) throws IllegalAccessException {
try {
klass.newInstance();
return true;
} catch (InstantiationException ex) {
return false;
}
}
public static boolean canDiscoverMethodWithMetaReflection(Class<?> klass, String name,
boolean hardeningEnabled) {
try {
setHiddenApiCheckHardening(hardeningEnabled);
Method metaGetDeclaredMethod =
Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);
// Assumes method without parameters.
return ((Method)metaGetDeclaredMethod.invoke(klass, name, null)) != null;
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
return false;
}
}
public static boolean canDiscoverFieldWithMetaReflection(Class<?> klass, String name,
boolean hardeningEnabled) {
try {
setHiddenApiCheckHardening(hardeningEnabled);
Method metaGetDeclaredField =
Class.class.getDeclaredMethod("getDeclaredField", String.class);
return ((Field)metaGetDeclaredField.invoke(klass, name)) != null;
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
return false;
}
}
public static boolean canDiscoverConstructorWithMetaReflection(Class<?> klass, Class<?> args[],
boolean hardeningEnabled) {
try {
setHiddenApiCheckHardening(hardeningEnabled);
Method metaGetDeclaredConstructor =
Class.class.getDeclaredMethod("getDeclaredConstructor", Class[].class);
return ((Constructor<?>)metaGetDeclaredConstructor.invoke(klass, (Object)args)) != null;
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
return false;
}
}
private static native int getHiddenApiAccessFlags();
private static native void setHiddenApiCheckHardening(boolean value);
public static boolean canObserveFieldHiddenAccessFlags(Class<?> klass, String name)
throws Exception {
return (klass.getDeclaredField(name).getModifiers() & getHiddenApiAccessFlags()) != 0;
}
public static boolean canObserveMethodHiddenAccessFlags(Class<?> klass, String name)
throws Exception {
return (klass.getDeclaredMethod(name).getModifiers() & getHiddenApiAccessFlags()) != 0;
}
public static boolean canObserveConstructorHiddenAccessFlags(Class<?> klass, Class<?> args[])
throws Exception {
return (klass.getConstructor(args).getModifiers() & getHiddenApiAccessFlags()) != 0;
}
}