245 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Java
		
	
	
	
| /*
 | |
|  * 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;
 | |
|   }
 | |
| }
 |