/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.acai;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* Internal Acai class which manages the execution of annotated methods on a {@link TestingService}.
*/
class TestingServiceManager {
private final TestingService testingService;
TestingServiceManager(TestingService testingService) {
this.testingService = checkNotNull(testingService);
}
/** Runs all methods annotated with {@code BeforeSuite}. */
void beforeSuite() {
invokeMethodsAnnotated(BeforeSuite.class);
}
/** Runs all methods annotated with {@code BeforeTest}. */
void beforeTest() {
invokeMethodsAnnotated(BeforeTest.class);
}
/** Runs all methods annotated with {@code AfterTest}. */
void afterTest() {
invokeMethodsAnnotated(AfterTest.class);
}
private void invokeMethodsAnnotated(Class<? extends Annotation> annotation) {
for (Method method : methodsAnnotated(annotation)) {
try {
method.setAccessible(true);
method.invoke(testingService);
} catch (InvocationTargetException e) {
if (e.getCause() != null) {
Throwables.throwIfUnchecked(e.getCause());
throw new RuntimeException(e.getCause());
}
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
private ImmutableList<Method> methodsAnnotated(Class<? extends Annotation> annotation) {
ImmutableList.Builder<Method> methods = ImmutableList.builder();
for (Class<?> clazz = testingService.getClass();
TestingService.class.isAssignableFrom(clazz);
clazz = clazz.getSuperclass()) {
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(annotation) && isUsable(method)) {
methods.add(method);
}
}
}
return methods.build();
}
/** Returns true if a method is suitable to be invoked by Acai. */
private static boolean isUsable(Method method) {
return !Modifier.isStatic(method.getModifiers()) && method.getParameterTypes().length == 0;
}
}