/**
* Copyright (c) 2014 Codetrails GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andreas Sewe - initial API and implementation.
*/
package org.eclipse.recommenders.utils;
import static org.eclipse.recommenders.utils.Logs.log;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.google.common.base.Optional;
public final class Reflections {
private Reflections() {
// Not meant to be instantiated
}
public static Optional<Class<?>> loadClass(@Nullable ClassLoader loader, @Nullable String name) {
return loadClass(false, loader, name);
}
public static Optional<Class<?>> loadClass(boolean isFunctionalityLimitedOnFailure, @Nullable ClassLoader loader,
@Nullable String name) {
if (loader == null || name == null) {
return Optional.absent();
}
try {
Class<?> clazz = loader.loadClass(name);
return Optional.<Class<?>>of(clazz);
} catch (ClassNotFoundException e) {
if (isFunctionalityLimitedOnFailure) {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_CLASS_REFLECTIVELY_LIMITED_FUNCTIONALITY, e, name);
}
return Optional.absent();
}
}
public static Optional<Field> getDeclaredField(@Nullable Class<?> declaringClass, @Nullable String name) {
return getDeclaredField(false, declaringClass, name);
}
public static Optional<Field> getDeclaredField(boolean isFunctionalityLimitedOnFailure,
@Nullable Class<?> declaringClass, @Nullable String name) {
if (declaringClass == null || name == null) {
return Optional.absent();
}
try {
Field field = declaringClass.getDeclaredField(name);
field.setAccessible(true);
return Optional.of(field);
} catch (NoSuchFieldException e) {
if (isFunctionalityLimitedOnFailure) {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_FIELD_REFLECTIVELY_LIMITED_FUNCTIONALITY, e, name,
declaringClass);
}
return Optional.absent();
} catch (SecurityException e) {
if (isFunctionalityLimitedOnFailure) {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_FIELD_REFLECTIVELY_LIMITED_FUNCTIONALITY, e, name,
declaringClass);
} else {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_FIELD_REFLECTIVELY, e, name, declaringClass);
}
return Optional.absent();
}
}
public static <T> Optional<Constructor<T>> getDeclaredConstructor(@Nullable Class<T> declaringClass,
@Nullable Class<?>... parameterTypes) {
return getDeclaredConstructor(false, declaringClass, parameterTypes);
}
public static <T> Optional<Constructor<T>> getDeclaredConstructor(boolean isFunctionalityLimitedOnFailure,
@Nullable Class<T> declaringClass, @Nullable Class<?>... parameterTypes) {
if (declaringClass == null || parameterTypes == null) {
return Optional.absent();
}
try {
Constructor<T> constructor = declaringClass.getDeclaredConstructor(parameterTypes);
constructor.setAccessible(true);
return Optional.of(constructor);
} catch (NoSuchMethodException e) {
if (isFunctionalityLimitedOnFailure) {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_CONSTRUCTOR_REFLECTIVELY_LIMITED_FUNCTIONALITY, e,
declaringClass);
}
return Optional.absent();
} catch (SecurityException e) {
if (isFunctionalityLimitedOnFailure) {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_CONSTRUCTOR_REFLECTIVELY_LIMITED_FUNCTIONALITY, e,
declaringClass);
} else {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_CONSTRUCTOR_REFLECTIVELY, e, declaringClass);
}
return Optional.absent();
}
}
public static Optional<Method> getDeclaredMethod(@Nullable Class<?> declaringClass, @Nullable String name,
@Nullable Class<?>... parameterTypes) {
return getDeclaredMethod(false, declaringClass, name, parameterTypes);
}
public static Optional<Method> getDeclaredMethod(boolean isFunctionalityLimitedOnFailure,
@Nullable Class<?> declaringClass, @Nullable String name, @Nullable Class<?>... parameterTypes) {
if (declaringClass == null || name == null || parameterTypes == null) {
return Optional.absent();
}
try {
Method method = declaringClass.getDeclaredMethod(name, parameterTypes);
method.setAccessible(true);
return Optional.of(method);
} catch (NoSuchMethodException e) {
if (isFunctionalityLimitedOnFailure) {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_METHOD_REFLECTIVELY_LIMITED_FUNCTIONALITY, e, name,
declaringClass);
}
return Optional.absent();
} catch (SecurityException e) {
if (isFunctionalityLimitedOnFailure) {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_METHOD_REFLECTIVELY_LIMITED_FUNCTIONALITY, e, name,
declaringClass);
} else {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_METHOD_REFLECTIVELY, e, name, declaringClass);
}
return Optional.absent();
}
}
public static Optional<Method> getDeclaredMethodWithAlternativeSignatures(@Nullable Class<?> declaringClass,
@Nullable String name, @Nullable Class<?>[]... parameterTypesAlternatives) {
return getDeclaredMethodWithAlternativeSignatures(false, declaringClass, name, parameterTypesAlternatives);
}
public static Optional<Method> getDeclaredMethodWithAlternativeSignatures(boolean isFunctionalityLimitedOnFailure,
@Nullable Class<?> declaringClass, @Nullable String name,
@Nullable Class<?>[]... parameterTypesAlternatives) {
if (declaringClass == null || name == null || parameterTypesAlternatives == null) {
return Optional.absent();
}
for (Class<?>[] parameterTypesAlternative : parameterTypesAlternatives) {
Optional<Method> declaredMethod = getDeclaredMethod(false, declaringClass, name, parameterTypesAlternative);
if (declaredMethod.isPresent()) {
return declaredMethod;
}
}
if (isFunctionalityLimitedOnFailure) {
log(LogMessages.LOG_WARNING_FAILED_TO_ACCESS_METHOD_REFLECTIVELY_LIMITED_FUNCTIONALITY, name,
declaringClass);
}
return Optional.absent();
}
}