1/*2 * Licensed to the Apache Software Foundation (ASF) under one3 * or more contributor license agreements. See the NOTICE file4 * distributed with this work for additional information5 * regarding copyright ownership. The ASF licenses this file6 * to you under the Apache License, Version 2.0 (the7 * "License"); you may not use this file except in compliance8 * with the License. You may obtain a copy of the License at9 *10 * http://www.apache.org/licenses/LICENSE-2.011 *12 * Unless required by applicable law or agreed to in writing, software13 * 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 and16 * limitations under the License.17 */1819package org.apache.giraph.utils;
2021import java.lang.reflect.Modifier;
2223import org.apache.giraph.conf.ContextSettable;
24import org.apache.giraph.conf.ImmutableClassesGiraphConfiguration;
25import org.apache.hadoop.mapreduce.Mapper;
26import org.jodah.typetools.TypeResolver;
2728/**29 * Helper methods to get type arguments to generic classes. Courtesy of30 * Ian Robertson (overstock.com). Make sure to use with abstract31 * generic classes, not interfaces.32 */33publicclassReflectionUtils {
34/**35 * Do not instantiate.36 */37privateReflectionUtils() { }
3839/**40 * Get package path to the object given. Used with resources.41 *42 * @param object the Object to check43 * @return Path to package of object44 */45publicstatic String getPackagePath(Object object) {
46return getPackagePath(object.getClass());
47 }
4849/**50 * Get package path to the class given. Used with resources.51 *52 * @param klass Class to check53 * @return Path to package of class54 */55publicstatic String getPackagePath(Class klass) {
56return klass.getPackage().getName().replaceAll("\\.", "/");
57 }
5859/**60 * Get the actual type arguments a child class has used to extend a61 * generic base class.62 *63 * @param <T> Type to evaluate.64 * @param baseClass the base class65 * @param childClass the child class66 * @return a list of the raw classes for the actual type arguments.67 */68publicstatic <T> Class<?>[] getTypeArguments(
69 Class<T> baseClass, Class<? extends T> childClass) {
70return TypeResolver.resolveArguments(childClass, baseClass);
71 }
7273/**74 * Instantiate a class, wrap exceptions75 *76 * @param theClass Class to instantiate77 * @param <T> Type to instantiate78 * @return Newly instantiated object79 */80 @SuppressWarnings("unchecked")
81publicstatic <T> T newInstance(Class<T> theClass) {
82try {
83return theClass.newInstance();
84 } catch (InstantiationException e) {
85thrownew IllegalStateException(
86"newInstance: Couldn't instantiate " + theClass.getName(), e);
87 } catch (IllegalAccessException e) {
88thrownew IllegalStateException(
89"newInstance: Illegal access " + theClass.getName(), e);
90 }
91 }
9293/**94 * Instantiate classes that are ImmutableClassesGiraphConfigurable95 *96 * @param theClass Class to instantiate97 * @param configuration Giraph configuration, may be null98 * @param <T> Type to instantiate99 * @return Newly instantiated object with configuration set if possible100 */101 @SuppressWarnings("unchecked")
102publicstatic <T> T newInstance(
103 Class<T> theClass,
104ImmutableClassesGiraphConfiguration configuration) {
105 T result;
106try {
107 result = theClass.newInstance();
108 } catch (InstantiationException e) {
109thrownew IllegalStateException(
110"newInstance: Couldn't instantiate " + theClass.getName(), e);
111 } catch (IllegalAccessException e) {
112thrownew IllegalStateException(
113"newInstance: Illegal access " + theClass.getName(), e);
114 }
115 ConfigurationUtils.configureIfPossible(result, configuration);
116return result;
117 }
118119/**120 * Instantiate classes that are ImmutableClassesGiraphConfigurable,121 * and optionally set context on them if they are ContextSettable122 *123 * @param theClass Class to instantiate124 * @param configuration Giraph configuration, may be null125 * @param context Mapper context126 * @param <T> Type to instantiate127 * @return Newly instantiated object with configuration and context set if128 * possible129 */130publicstatic <T> T newInstance(
131 Class<T> theClass,
132ImmutableClassesGiraphConfiguration configuration,
133 Mapper<?, ?, ?, ?>.Context context) {
134 T result = newInstance(theClass, configuration);
135if (result instanceof ContextSettable) {
136 ((ContextSettable) result).setContext(context);
137 }
138return result;
139 }
140141/**142 * Verify that found type matches the expected type. If types don't match an143 * {@link IllegalStateException} will be thrown.144 *145 * @param concreteChild Concrete child type146 * @param parent Parent type147 * @param typeDesc String description of the type (for exception description)148 * @param mainClass Class in which the actual type was found (for exception149 * description)150 */151publicstaticvoid verifyTypes(Class<?> concreteChild, Class<?> parent,
152 String typeDesc, Class<?> mainClass) {
153// unknown means object154if (parent == TypeResolver.Unknown.class) {
155 parent = Object.class;
156 }
157158 verifyConcrete(concreteChild, typeDesc);
159160if (!parent.isAssignableFrom(concreteChild)) {
161thrownew IllegalStateException("verifyTypes: " + typeDesc + " types " +
162"don't match, in " + mainClass.getName() + " " + concreteChild +
163" expected, but " + parent + " found");
164 }
165 }
166167/**168 * Verify that given type is a concrete type that can be instantiated.169 *170 * @param concrete type to check171 * @param typeDesc String description of the type (for exception description)172 */173publicstaticvoid verifyConcrete(
174 Class<?> concrete, String typeDesc) {
175if (concrete.isInterface()) {
176thrownew IllegalStateException("verifyTypes: " +
177"Type " + typeDesc + " must be concrete class " + concrete);
178 }
179if (Modifier.isAbstract(concrete.getModifiers())) {
180thrownew IllegalStateException("verifyTypes: " +
181"Type " + typeDesc + "can't be abstract class" + concrete);
182 }
183 }
184 }