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.ContextSettable;
24 import org.apache.giraph.conf.ImmutableClassesGiraphConfiguration;
25 import org.apache.hadoop.mapreduce.Mapper;
26 import org.jodah.typetools.TypeResolver;
27
28 /**
29 * Helper methods to get type arguments to generic classes. Courtesy of
30 * Ian Robertson (overstock.com). Make sure to use with abstract
31 * generic classes, not interfaces.
32 */
33 public class ReflectionUtils {
34 /**
35 * Do not instantiate.
36 */
37 private ReflectionUtils() { }
38
39 /**
40 * Get package path to the object given. Used with resources.
41 *
42 * @param object the Object to check
43 * @return Path to package of object
44 */
45 public static String getPackagePath(Object object) {
46 return getPackagePath(object.getClass());
47 }
48
49 /**
50 * Get package path to the class given. Used with resources.
51 *
52 * @param klass Class to check
53 * @return Path to package of class
54 */
55 public static String getPackagePath(Class klass) {
56 return klass.getPackage().getName().replaceAll("\\.", "/");
57 }
58
59 /**
60 * Get the actual type arguments a child class has used to extend a
61 * generic base class.
62 *
63 * @param <T> Type to evaluate.
64 * @param baseClass the base class
65 * @param childClass the child class
66 * @return a list of the raw classes for the actual type arguments.
67 */
68 public static <T> Class<?>[] getTypeArguments(
69 Class<T> baseClass, Class<? extends T> childClass) {
70 return TypeResolver.resolveArguments(childClass, baseClass);
71 }
72
73 /**
74 * Instantiate a class, wrap exceptions
75 *
76 * @param theClass Class to instantiate
77 * @param <T> Type to instantiate
78 * @return Newly instantiated object
79 */
80 @SuppressWarnings("unchecked")
81 public static <T> T newInstance(Class<T> theClass) {
82 try {
83 return theClass.newInstance();
84 } catch (InstantiationException e) {
85 throw new IllegalStateException(
86 "newInstance: Couldn't instantiate " + theClass.getName(), e);
87 } catch (IllegalAccessException e) {
88 throw new IllegalStateException(
89 "newInstance: Illegal access " + theClass.getName(), e);
90 }
91 }
92
93 /**
94 * Instantiate classes that are ImmutableClassesGiraphConfigurable
95 *
96 * @param theClass Class to instantiate
97 * @param configuration Giraph configuration, may be null
98 * @param <T> Type to instantiate
99 * @return Newly instantiated object with configuration set if possible
100 */
101 @SuppressWarnings("unchecked")
102 public static <T> T newInstance(
103 Class<T> theClass,
104 ImmutableClassesGiraphConfiguration configuration) {
105 T result;
106 try {
107 result = theClass.newInstance();
108 } catch (InstantiationException e) {
109 throw new IllegalStateException(
110 "newInstance: Couldn't instantiate " + theClass.getName(), e);
111 } catch (IllegalAccessException e) {
112 throw new IllegalStateException(
113 "newInstance: Illegal access " + theClass.getName(), e);
114 }
115 ConfigurationUtils.configureIfPossible(result, configuration);
116 return result;
117 }
118
119 /**
120 * Instantiate classes that are ImmutableClassesGiraphConfigurable,
121 * and optionally set context on them if they are ContextSettable
122 *
123 * @param theClass Class to instantiate
124 * @param configuration Giraph configuration, may be null
125 * @param context Mapper context
126 * @param <T> Type to instantiate
127 * @return Newly instantiated object with configuration and context set if
128 * possible
129 */
130 public static <T> T newInstance(
131 Class<T> theClass,
132 ImmutableClassesGiraphConfiguration configuration,
133 Mapper<?, ?, ?, ?>.Context context) {
134 T result = newInstance(theClass, configuration);
135 if (result instanceof ContextSettable) {
136 ((ContextSettable) result).setContext(context);
137 }
138 return result;
139 }
140
141 /**
142 * Verify that found type matches the expected type. If types don't match an
143 * {@link IllegalStateException} will be thrown.
144 *
145 * @param concreteChild Concrete child type
146 * @param parent Parent type
147 * @param typeDesc String description of the type (for exception description)
148 * @param mainClass Class in which the actual type was found (for exception
149 * description)
150 */
151 public static void verifyTypes(Class<?> concreteChild, Class<?> parent,
152 String typeDesc, Class<?> mainClass) {
153 // unknown means object
154 if (parent == TypeResolver.Unknown.class) {
155 parent = Object.class;
156 }
157
158 verifyConcrete(concreteChild, typeDesc);
159
160 if (!parent.isAssignableFrom(concreteChild)) {
161 throw new IllegalStateException("verifyTypes: " + typeDesc + " types " +
162 "don't match, in " + mainClass.getName() + " " + concreteChild +
163 " expected, but " + parent + " found");
164 }
165 }
166
167 /**
168 * Verify that given type is a concrete type that can be instantiated.
169 *
170 * @param concrete type to check
171 * @param typeDesc String description of the type (for exception description)
172 */
173 public static void verifyConcrete(
174 Class<?> concrete, String typeDesc) {
175 if (concrete.isInterface()) {
176 throw new IllegalStateException("verifyTypes: " +
177 "Type " + typeDesc + " must be concrete class " + concrete);
178 }
179 if (Modifier.isAbstract(concrete.getModifiers())) {
180 throw new IllegalStateException("verifyTypes: " +
181 "Type " + typeDesc + "can't be abstract class" + concrete);
182 }
183 }
184 }