package detective.core.distribute.collector; import groovy.lang.Script; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import detective.common.ClassUtils; import detective.core.Detective; import detective.core.Scenario; import detective.core.Story; import detective.core.distribute.JobToRun; import detective.core.filter.FilterChainFactory; import detective.core.filter.RunnerFilter; import detective.core.filter.RunnerFilterChain; import detective.core.runner.DslBuilderAndRun; import detective.core.runner.RunnerInterceptor; import detective.core.runner.SimpleStoryRunner; /** * Please be very careful, this class will change DslBuilderAndRun behavior to run storys * in spark not the normal process * * @author James Luo * */ public class JobCollector { private static Logger logger = LoggerFactory.getLogger(JobCollector.class); private FilterChainFactory chainFactory; private JobCollector(){ try { chainFactory = FilterChainFactory.ConfigReader.instanceFromConfigFile("runner.spark_distribute.filter_chain_factory"); } catch (Exception e) { throw new RuntimeException(e); } DslBuilderAndRun.setFilterChainCurrentThread((RunnerFilterChain<Story>) chainFactory.getChain()); } private List<JobToRun> getJobs(){ for (RunnerFilter<?> filter : chainFactory.getChain()){ if (filter instanceof JobCollectorFilter){ return ((JobCollectorFilter)filter).getJobs(); } } throw new RuntimeException("No detective.core.distribute.JobCollectorFilter found in filter chain : " + chainFactory.getClass().getName()); } private void shutdown(){ DslBuilderAndRun.setFilterChainCurrentThread(null); } /** * * @param duplicates how many jobs you'd like to duplicate * @return */ public static List<JobToRun> collectAll(String packageOrClassName, int duplicates){ List<JobToRun> jobs = collectAll(packageOrClassName); List<JobToRun> duplicatedJobs = new ArrayList<JobToRun>(); if (duplicates > 0){ for (int i = 0; i < duplicates; i++){ duplicatedJobs.addAll(jobs); } } return duplicatedJobs; } public static List<JobToRun> collectAll(String packageOrClassName){ List<JobToRun> jobs = new ArrayList<JobToRun>(); try { List<Class<?>> classes = collectClass(packageOrClassName); if (classes == null || classes.size() == 0) classes = ClassUtils.getClassesForPackage(packageOrClassName); for (Class<?> clazz : classes){ //if (clazz.isAssignableFrom(Script.class)){ //not work for some reason if (clazz.getSuperclass().getName().equals("groovy.lang.Script")){ jobs.addAll(collectJobs(clazz)); }else{ //logger.warn(clazz.getName() + " is not a groovy script or story, ignored."); //Don't log, too much info } } } catch (Exception e) { Detective.error(e.getMessage(), e); } return jobs; } private static List<Class<?>> collectClass(String className){ try { Class<?> clazz = Class.forName(className); List<Class<?>> result = new ArrayList<Class<?>>(); result.add(clazz); return result; } catch (ClassNotFoundException e) { return null; } } private static List<JobToRun> collectJobs(Class<?> clazz) throws InstantiationException, IllegalAccessException { JobCollector dis = new JobCollector(); try{ Script script = (Script)clazz.newInstance(); script.run(); for (JobToRun job : dis.getJobs()) job.setStoryClassName(clazz.getName()); }finally{ dis.shutdown(); } return dis.getJobs(); } }