• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 package com.android.layoutlib.bridge.util;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 
22 import java.lang.reflect.InvocationTargetException;
23 import java.lang.reflect.Method;
24 
25 /**
26  * Utility to convert checked Reflection exceptions to unchecked exceptions.
27  */
28 public class ReflectionUtils {
29 
30     @NonNull
getMethod(@onNull Class<?> clazz, @NonNull String name, @Nullable Class<?>... params)31     public static Method getMethod(@NonNull Class<?> clazz, @NonNull String name,
32             @Nullable Class<?>... params) throws ReflectionException {
33         try {
34             return clazz.getMethod(name, params);
35         } catch (NoSuchMethodException e) {
36             throw new ReflectionException(e);
37         }
38     }
39 
40     @NonNull
getAccessibleMethod(@onNull Class<?> clazz, @NonNull String name, @Nullable Class<?>... params)41     public static Method getAccessibleMethod(@NonNull Class<?> clazz, @NonNull String name,
42       @Nullable Class<?>... params) throws ReflectionException {
43         Method method = getMethod(clazz, name, params);
44         method.setAccessible(true);
45 
46         return method;
47     }
48 
49     @Nullable
invoke(@onNull Method method, @Nullable Object object, @Nullable Object... args)50     public static Object invoke(@NonNull Method method, @Nullable Object object,
51             @Nullable Object... args) throws ReflectionException {
52         Exception ex;
53         try {
54             return method.invoke(object, args);
55         } catch (IllegalAccessException | InvocationTargetException e) {
56             ex = e;
57         }
58         throw new ReflectionException(ex);
59     }
60 
61     /**
62      * Check if the object is an instance of a class named {@code className}. This doesn't work
63      * for interfaces.
64      */
isInstanceOf(Object object, String className)65     public static boolean isInstanceOf(Object object, String className) {
66         Class superClass = object.getClass();
67         while (superClass != null) {
68             String name = superClass.getName();
69             if (name.equals(className)) {
70                 return true;
71             }
72             superClass = superClass.getSuperclass();
73         }
74         return false;
75     }
76 
77     @NonNull
getCause(@onNull Throwable throwable)78     public static Throwable getCause(@NonNull Throwable throwable) {
79         Throwable cause = throwable.getCause();
80         return cause == null ? throwable : cause;
81     }
82 
83     /**
84      * Looks through the class hierarchy of {@code object} at runtime and returns the class matching
85      * the name {@code className}.
86      * <p>
87      * This is used when we cannot use Class.forName() since the class we want was loaded from a
88      * different ClassLoader.
89      */
90     @NonNull
getClassInstance(@onNull Object object, @NonNull String className)91     public static Class<?> getClassInstance(@NonNull Object object, @NonNull String className) {
92         Class<?> superClass = object.getClass();
93         while (superClass != null) {
94             if (className.equals(superClass.getName())) {
95                 return superClass;
96             }
97             superClass = superClass.getSuperclass();
98         }
99         throw new RuntimeException("invalid object/classname combination.");
100     }
101 
102     /**
103      * Wraps all reflection related exceptions. Created since ReflectiveOperationException was
104      * introduced in 1.7 and we are still on 1.6
105      */
106     public static class ReflectionException extends Exception {
ReflectionException()107         public ReflectionException() {
108             super();
109         }
110 
ReflectionException(String message)111         public ReflectionException(String message) {
112             super(message);
113         }
114 
ReflectionException(String message, Throwable cause)115         public ReflectionException(String message, Throwable cause) {
116             super(message, cause);
117         }
118 
ReflectionException(Throwable cause)119         public ReflectionException(Throwable cause) {
120             super(cause);
121         }
122     }
123 }
124