View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.util;
20  
21  import java.lang.reflect.Constructor;
22  import java.lang.reflect.InvocationTargetException;
23  
24  import org.apache.hadoop.classification.InterfaceAudience;
25  
26  @InterfaceAudience.Private
27  public class ReflectionUtils {
28    @SuppressWarnings("unchecked")
29    public static <T> T instantiateWithCustomCtor(String className,
30        Class<? >[] ctorArgTypes, Object[] ctorArgs) {
31      try {
32        Class<? extends T> resultType = (Class<? extends T>) Class.forName(className);
33        Constructor<? extends T> ctor = resultType.getDeclaredConstructor(ctorArgTypes);
34        return instantiate(className, ctor, ctorArgs);
35      } catch (ClassNotFoundException e) {
36        throw new UnsupportedOperationException(
37            "Unable to find " + className, e);
38      } catch (NoSuchMethodException e) {
39        throw new UnsupportedOperationException(
40            "Unable to find suitable constructor for class " + className, e);
41      }
42    }
43  
44    private static <T> T instantiate(final String className, Constructor<T> ctor, Object[] ctorArgs) {
45      try {
46        return ctor.newInstance(ctorArgs);
47      } catch (IllegalAccessException e) {
48        throw new UnsupportedOperationException(
49            "Unable to access specified class " + className, e);
50      } catch (InstantiationException e) {
51        throw new UnsupportedOperationException(
52            "Unable to instantiate specified class " + className, e);
53      } catch (InvocationTargetException e) {
54        throw new UnsupportedOperationException(
55            "Constructor threw an exception for " + className, e);
56      }
57    }
58  
59    @SuppressWarnings("unchecked")
60    public static <T> T newInstance(Class<T> type, Object... params) {
61      return instantiate(type.getName(), findConstructor(type, params), params);
62    }
63  
64    @SuppressWarnings("unchecked")
65    public static <T> Constructor<T> findConstructor(Class<T> type, Object... paramTypes) {
66      Constructor<T>[] constructors = (Constructor<T>[])type.getConstructors();
67      for (Constructor<T> ctor : constructors) {
68        Class<?>[] ctorParamTypes = ctor.getParameterTypes();
69        if (ctorParamTypes.length != paramTypes.length) {
70          continue;
71        }
72  
73        boolean match = true;
74        for (int i = 0; i < ctorParamTypes.length && match; ++i) {
75          Class<?> paramType = paramTypes[i].getClass();
76          match = (!ctorParamTypes[i].isPrimitive()) ? ctorParamTypes[i].isAssignableFrom(paramType) :
77                    ((int.class.equals(ctorParamTypes[i]) && Integer.class.equals(paramType)) ||
78                     (long.class.equals(ctorParamTypes[i]) && Long.class.equals(paramType)) ||
79                     (char.class.equals(ctorParamTypes[i]) && Character.class.equals(paramType)) ||
80                     (short.class.equals(ctorParamTypes[i]) && Short.class.equals(paramType)) ||
81                     (boolean.class.equals(ctorParamTypes[i]) && Boolean.class.equals(paramType)) ||
82                     (byte.class.equals(ctorParamTypes[i]) && Byte.class.equals(paramType)));
83        }
84  
85        if (match) {
86          return ctor;
87        }
88      }
89      throw new UnsupportedOperationException(
90        "Unable to find suitable constructor for class " + type.getName());
91    }
92  }