View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.giraph.utils;
20  
21  import java.lang.reflect.Modifier;
22  
23  import org.apache.giraph.conf.ImmutableClassesGiraphConfiguration;
24  import org.jodah.typetools.TypeResolver;
25  
26  /**
27   * Helper methods to get type arguments to generic classes.  Courtesy of
28   * Ian Robertson (overstock.com).  Make sure to use with abstract
29   * generic classes, not interfaces.
30   */
31  public class ReflectionUtils {
32    /**
33     * Do not instantiate.
34     */
35    private ReflectionUtils() { }
36  
37    /**
38     * Get package path to the object given. Used with resources.
39     *
40     * @param object the Object to check
41     * @return Path to package of object
42     */
43    public static String getPackagePath(Object object) {
44      return getPackagePath(object.getClass());
45    }
46  
47    /**
48     * Get package path to the class given. Used with resources.
49     *
50     * @param klass Class to check
51     * @return Path to package of class
52     */
53    public static String getPackagePath(Class klass) {
54      return klass.getPackage().getName().replaceAll("\\.", "/");
55    }
56  
57    /**
58     * Get the actual type arguments a child class has used to extend a
59     * generic base class.
60     *
61     * @param <T> Type to evaluate.
62     * @param baseClass the base class
63     * @param childClass the child class
64     * @return a list of the raw classes for the actual type arguments.
65     */
66    public static <T> Class<?>[] getTypeArguments(
67        Class<T> baseClass, Class<? extends T> childClass) {
68      return TypeResolver.resolveArguments(childClass, baseClass);
69    }
70  
71    /**
72     * Instantiate a class, wrap exceptions
73     *
74     * @param theClass Class to instantiate
75     * @param <T> Type to instantiate
76     * @return Newly instantiated object
77     */
78    @SuppressWarnings("unchecked")
79    public static <T> T newInstance(Class<T> theClass) {
80      try {
81        return theClass.newInstance();
82      } catch (InstantiationException e) {
83        throw new IllegalStateException(
84            "newInstance: Couldn't instantiate " + theClass.getName(), e);
85      } catch (IllegalAccessException e) {
86        throw new IllegalStateException(
87            "newInstance: Illegal access " + theClass.getName(), e);
88      }
89    }
90  
91    /**
92     * Instantiate classes that are ImmutableClassesGiraphConfigurable
93     *
94     * @param theClass Class to instantiate
95     * @param configuration Giraph configuration, may be null
96     * @param <T> Type to instantiate
97     * @return Newly instantiated object with configuration set if possible
98     */
99    @SuppressWarnings("unchecked")
100   public static <T> T newInstance(
101       Class<T> theClass,
102       ImmutableClassesGiraphConfiguration configuration) {
103     T result;
104     try {
105       result = theClass.newInstance();
106     } catch (InstantiationException e) {
107       throw new IllegalStateException(
108           "newInstance: Couldn't instantiate " + theClass.getName(), e);
109     } catch (IllegalAccessException e) {
110       throw new IllegalStateException(
111           "newInstance: Illegal access " + theClass.getName(), e);
112     }
113     ConfigurationUtils.configureIfPossible(result, configuration);
114     return result;
115   }
116 
117   /**
118    * Verify that found type matches the expected type. If types don't match an
119    * {@link IllegalStateException} will be thrown.
120    *
121    * @param concreteChild Concrete child type
122    * @param parent Parent type
123    * @param typeDesc String description of the type (for exception description)
124    * @param mainClass Class in which the actual type was found (for exception
125    *                  description)
126    */
127   public static void verifyTypes(Class<?> concreteChild, Class<?> parent,
128       String typeDesc, Class<?> mainClass) {
129     // unknown means object
130     if (parent == TypeResolver.Unknown.class) {
131       parent = Object.class;
132     }
133 
134     verifyConcrete(concreteChild, typeDesc);
135 
136     if (!parent.isAssignableFrom(concreteChild)) {
137       throw new IllegalStateException("verifyTypes: " + typeDesc + " types " +
138           "don't match, in " + mainClass.getName() + " " + concreteChild +
139           " expected, but " + parent + " found");
140     }
141   }
142 
143   /**
144    * Verify that given type is a concrete type that can be instantiated.
145    *
146    * @param concrete type to check
147    * @param typeDesc String description of the type (for exception description)
148    */
149   public static void verifyConcrete(
150       Class<?> concrete, String typeDesc) {
151     if (concrete.isInterface()) {
152       throw new IllegalStateException("verifyTypes: " +
153           "Type " + typeDesc + " must be concrete class " + concrete);
154     }
155     if (Modifier.isAbstract(concrete.getModifiers())) {
156       throw new IllegalStateException("verifyTypes: " +
157           "Type " + typeDesc + "can't be abstract class" + concrete);
158     }
159   }
160 }