package org.radargun.reporting;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.radargun.Directories;
import org.radargun.config.Definition;
import org.radargun.config.InitHelper;
import org.radargun.config.PropertyHelper;
import org.radargun.logging.Log;
import org.radargun.logging.LogFactory;
import org.radargun.utils.ArgsHolder;
import org.radargun.utils.Utils;
/**
* Helper class creating reporters (in their own classloaders).
* Each reporter module (directory) should contain JAR with file plugin.properties.
* This file lists all reporter as reporter./reporter type/ /reporter class/
*
* @author Radim Vansa <rvansa@redhat.com>
*/
public final class ReporterHelper {
private static final String REPORTER_PREFIX = "reporter.";
private static final Log log = LogFactory.getLog(ReporterHelper.class);
private static final Map<String, Class<? extends Reporter>> REPORTERS = new HashMap<>();
static {
for (File reporterDir : Directories.REPORTERS_DIR.listFiles()) {
loadReporters(reporterDir, REPORTERS);
}
for (String path : ArgsHolder.getReporterPaths()) {
loadReporters(new File(path), REPORTERS);
}
}
private ReporterHelper() {}
public static void registerReporters(String reporterDir) {
loadReporters(new File(reporterDir), REPORTERS);
}
public static void loadReporters(File reporterDir, Map<String, Class<? extends Reporter>> reporters) {
try {
if (!reporterDir.isDirectory()) {
log.warn(reporterDir + " is not a directory");
return;
}
List<URL> urls = new ArrayList<>();
Properties properties = null;
for (File jar : reporterDir.listFiles(new Utils.JarFilenameFilter())) {
urls.add(jar.toURI().toURL());
if (properties == null) {
properties = Utils.getJarProperties(jar);
}
}
if (urls.isEmpty()) {
log.warn("No JARs in " + reporterDir);
return;
}
ClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), ReporterHelper.class.getClassLoader());
for (String propertyName : properties.stringPropertyNames()) {
if (propertyName.startsWith(REPORTER_PREFIX)) {
String type = propertyName.substring(REPORTER_PREFIX.length());
String clazzName = properties.getProperty(propertyName);
if (reporters.containsKey(type)) {
throw new IllegalStateException("Reporter for type " + type + " already registered: " + reporters.get(type));
} else {
log.debug("Registering reporter '" + type + "' using " + clazzName);
try {
Class<? extends Reporter> reporterClazz = (Class<? extends Reporter>) classLoader.loadClass(clazzName);
reporters.put(type, reporterClazz);
} catch (ClassNotFoundException e) {
log.error("Failed to load reporter class " + clazzName + " for type '" + type + "'");
}
}
}
}
} catch (IOException e) {
throw new RuntimeException("Failed to load properties from " + reporterDir, e);
}
}
/**
* Searches for a reporter with particular name.
* @param type Name of the reporter
* @return True if reporter with this name was found.
*/
public static boolean isRegistered(String type) {
return REPORTERS.containsKey(type);
}
/**
* Create a reporter with given type
* @param type
* @param properties
* @return
*/
public static Reporter createReporter(String type, Map<String, Definition> properties) {
Class<? extends Reporter> clazz = REPORTERS.get(type);
if (clazz == null) {
throw new IllegalArgumentException("Reporter for type '" + type + "' was not found");
}
try {
Reporter instance = clazz.newInstance();
PropertyHelper.setPropertiesFromDefinitions(instance, properties, false, true);
InitHelper.init(instance);
return instance;
} catch (Exception e) {
throw new RuntimeException("Cannot create reporter with class " + clazz, e);
}
}
public static Set<String> getReporterNames() {
return Collections.unmodifiableSet(REPORTERS.keySet());
}
}