View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shardingsphere.infra.util.reflection;
19  
20  import com.google.common.base.CaseFormat;
21  import lombok.AccessLevel;
22  import lombok.NoArgsConstructor;
23  import lombok.SneakyThrows;
24  
25  import java.lang.reflect.Field;
26  import java.lang.reflect.Method;
27  import java.util.Optional;
28  
29  /**
30   * Reflection utility class.
31   */
32  @NoArgsConstructor(access = AccessLevel.PRIVATE)
33  public final class ReflectionUtils {
34      
35      private static final String GETTER_PREFIX = "get";
36      
37      /**
38       * Get field value.
39       * 
40       * @param target target
41       * @param fieldName field name
42       * @param <T> type of field value
43       * @return field value
44       */
45      public static <T> Optional<T> getFieldValue(final Object target, final String fieldName) {
46          return findField(fieldName, target.getClass()).map(optional -> getFieldValue(target, optional));
47      }
48      
49      @SuppressWarnings("unchecked")
50      @SneakyThrows(IllegalAccessException.class)
51      private static <T> T getFieldValue(final Object target, final Field field) {
52          boolean accessible = field.isAccessible();
53          if (!accessible) {
54              field.setAccessible(true);
55          }
56          T result = (T) field.get(target);
57          if (!accessible) {
58              field.setAccessible(false);
59          }
60          return result;
61      }
62      
63      private static Optional<Field> findField(final String fieldName, final Class<?> targetClass) {
64          Class<?> currentTargetClass = targetClass;
65          while (Object.class != currentTargetClass) {
66              try {
67                  return Optional.of(currentTargetClass.getDeclaredField(fieldName));
68              } catch (final NoSuchFieldException ignored) {
69                  currentTargetClass = currentTargetClass.getSuperclass();
70              }
71          }
72          return Optional.empty();
73      }
74      
75      /**
76       * Get static field value.
77       *
78       * @param target target
79       * @param fieldName field name
80       * @param <T> type of field value
81       * @return field value
82       */
83      @SuppressWarnings("unchecked")
84      @SneakyThrows(ReflectiveOperationException.class)
85      public static <T> T getStaticFieldValue(final Class<?> target, final String fieldName) {
86          Field field = target.getDeclaredField(fieldName);
87          boolean accessible = field.isAccessible();
88          if (!accessible) {
89              field.setAccessible(true);
90          }
91          T result = (T) field.get(target);
92          if (!accessible) {
93              field.setAccessible(false);
94          }
95          return result;
96      }
97      
98      /**
99       * Set static field value.
100      * 
101      * @param target target
102      * @param fieldName field name
103      * @param value value
104      */
105     @SneakyThrows(ReflectiveOperationException.class)
106     public static void setStaticFieldValue(final Class<?> target, final String fieldName, final Object value) {
107         Field field = target.getDeclaredField(fieldName);
108         boolean accessible = field.isAccessible();
109         if (!accessible) {
110             field.setAccessible(true);
111         }
112         field.set(target, value);
113         if (!accessible) {
114             field.setAccessible(false);
115         }
116     }
117     
118     /**
119      * Invoke method.
120      *
121      * @param method method
122      * @param target target
123      * @param args arguments
124      * @param <T> type of invoke result
125      * @return invoke result
126      */
127     @SuppressWarnings("unchecked")
128     @SneakyThrows(ReflectiveOperationException.class)
129     public static <T> T invokeMethod(final Method method, final Object target, final Object... args) {
130         boolean accessible = method.isAccessible();
131         if (!accessible) {
132             method.setAccessible(true);
133         }
134         T result = (T) method.invoke(target, args);
135         if (!accessible) {
136             method.setAccessible(false);
137         }
138         return result;
139     }
140     
141     /**
142      * Get field value by get method.
143      *
144      * @param target target
145      * @param fieldName field name
146      * @param <T> type of field value
147      * @return field value
148      */
149     public static <T> Optional<T> getFieldValueByGetMethod(final Object target, final String fieldName) {
150         String getterName = GETTER_PREFIX + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, fieldName);
151         final Optional<Method> method = findMethod(target.getClass(), getterName);
152         if (method.isPresent()) {
153             T value = invokeMethod(method.get(), target);
154             return Optional.ofNullable(value);
155         } else {
156             return Optional.empty();
157         }
158     }
159     
160     private static Optional<Method> findMethod(final Class<?> clazz, final String methodName, final Class<?>... parameterTypes) {
161         try {
162             return Optional.of(clazz.getMethod(methodName, parameterTypes));
163         } catch (final NoSuchMethodException ex) {
164             Class<?> superclass = clazz.getSuperclass();
165             if (null != superclass && Object.class != superclass) {
166                 return findMethod(superclass, methodName, parameterTypes);
167             }
168         }
169         return Optional.empty();
170     }
171 }