com.farao_community.farao.rao_runner.app.GenericThreadLauncher Maven / Gradle / Ivy
/*
* Copyright (c) 2022, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.farao_community.farao.rao_runner.app;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.farao_community.farao.rao_runner.api.exceptions.RaoRunnerException;
import com.farao_community.farao.rao_runner.api.resource.ThreadLauncherResult;
import org.slf4j.MDC;
public class GenericThreadLauncher extends Thread {
private final T threadable;
private final Method run;
private final Object[] args;
private final Map contextMap;
private ThreadLauncherResult result;
public GenericThreadLauncher(T threadable, String id, Map contextMap, Object... args) {
super(id);
this.run = getMethodAnnotatedWith(threadable.getClass());
this.threadable = threadable;
this.args = args;
this.contextMap = new HashMap<>(contextMap);
}
@Override
public void run() {
try {
contextMap.forEach(MDC::put);
U threadResult = (U) this.run.invoke(threadable, args);
this.result = ThreadLauncherResult.success(threadResult);
} catch (IllegalAccessException | InvocationTargetException e) {
if (result == null) {
this.result = ThreadLauncherResult.error(e);
}
}
}
@Override
public void interrupt() {
this.result = ThreadLauncherResult.interrupt();
super.interrupt();
}
public ThreadLauncherResult getResult() {
try {
join();
} catch (InterruptedException e) {
interrupt();
}
return result;
}
private static Method getMethodAnnotatedWith(final Class> type) {
List methods = getMethodsAnnotatedWith(type);
if (methods.isEmpty()) {
throw new RaoRunnerException("the class " + type.getCanonicalName() + " does not have his running method annotated with @Threadable");
} else if (methods.size() > 1) {
throw new RaoRunnerException("the class " + type.getCanonicalName() + " must have only one method annotated with @Threadable");
} else {
return methods.get(0);
}
}
private static List getMethodsAnnotatedWith(final Class> type) {
final List methods = new ArrayList<>();
Class> klass = type;
while (klass != Object.class) { // need to traverse a type hierarchy in order to process methods from super types
// iterate though the list of methods declared in the class represented by klass variable, and add those annotated with the specified annotation
for (final Method method : klass.getDeclaredMethods()) {
if (method.isAnnotationPresent(Threadable.class)) {
methods.add(method);
}
}
// move to the upper class in the hierarchy in search for more methods
klass = klass.getSuperclass();
}
return methods;
}
}