package org.arquillian.cube.docker.impl.util;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class ContainerObjectUtil {
private ContainerObjectUtil() {
super();
}
public static <T extends Annotation> List<T> getAllAnnotations(final Class<?> source,
final Class<T> annotationClass) {
return AccessController.doPrivileged((PrivilegedAction<List<T>>) () -> {
List<T> annotations = new ArrayList<>();
Class<?> nextSource = source;
while (nextSource != Object.class) {
final T[] annotationsByType = nextSource.getAnnotationsByType(annotationClass);
Collections.addAll(annotations, annotationsByType);
//If not maybe we need to use the default value but maybe there is some parent class
//That contains a different value rather than the default ones so we need to continue search.
nextSource = nextSource.getSuperclass();
}
return annotations;
});
}
public static <T> T getTopCubeAttribute(final Class<?> source, final String nameField,
final Class<? extends Annotation> annotationClass, final T defaultValue) {
return AccessController.doPrivileged((PrivilegedAction<T>) () -> {
Method field = null;
try {
field = annotationClass.getMethod(nameField);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(e);
}
Class<?> nextSource = source;
boolean foundAnnotation = false;
while (nextSource != Object.class) {
if (nextSource.isAnnotationPresent(annotationClass)) {
foundAnnotation = true;
final Annotation annotation = nextSource.getAnnotation(annotationClass);
final T value = getValue(annotation, field);
//If it is not the default value means that we have found a top level definition
if (defaultValue.getClass().isArray()) {
if (defaultValue.getClass().getComponentType().isPrimitive()) {
// Only works with integer primitives or CCE
if (!Arrays.equals((int[]) value, (int[]) defaultValue)) {
return value;
}
} else {
if (!Arrays.equals((Object[]) value, (Object[]) defaultValue)) {
return value;
}
}
} else {
if (!value.equals(defaultValue)) {
return value;
}
}
}
//If not maybe we need to use the default value but maybe there is some parent class
//That contains a different value rather than the default ones so we need to continue search.
nextSource = nextSource.getSuperclass();
}
return foundAnnotation ? defaultValue : null;
});
}
@SuppressWarnings("unchecked")
private static <T> T getValue(final Annotation annotation, Method field) {
try {
return (T) field.invoke(annotation);
} catch (InvocationTargetException | IllegalAccessException e) {
throw new IllegalArgumentException(e);
}
}
}