You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
7.4 KiB
245 lines
7.4 KiB
/*
|
|
* 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;
|
|
}
|
|
}
|