package org.easyrec.plugin.configuration; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Lists; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.easyrec.model.plugin.LogEntry; import org.easyrec.model.plugin.NamedConfiguration; import org.easyrec.plugin.container.PluginRegistry; import org.easyrec.plugin.generator.Generator; import org.easyrec.plugin.generator.GeneratorConfiguration; import org.easyrec.plugin.stats.GeneratorStatistics; import org.easyrec.plugin.stats.StatisticsConstants; import org.easyrec.store.dao.core.types.AssocTypeDAO; import org.easyrec.store.dao.plugin.LogEntryDAO; import org.easyrec.store.dao.plugin.NamedConfigurationDAO; import java.util.Date; import java.util.List; import java.util.Map; public class GeneratorContainer { private static final Log logger = LogFactory.getLog(GeneratorContainer.class); public GeneratorContainer(AssocTypeDAO assocTypeDAO, NamedConfigurationDAO namedConfigurationDAO, LogEntryDAO logEntryDAO, PluginRegistry registry) { this.assocTypeDAO = assocTypeDAO; this.namedConfigurationDAO = namedConfigurationDAO; this.logEntryDAO = logEntryDAO; this.registry = registry; } private AssocTypeDAO assocTypeDAO; private NamedConfigurationDAO namedConfigurationDAO; private LogEntryDAO logEntryDAO; private PluginRegistry registry; public LogEntry runGenerator(NamedConfiguration namedConfiguration) { return runGenerator(namedConfiguration, Predicates.<GeneratorStatistics>alwaysTrue()); } public LogEntry runGenerator(NamedConfiguration namedConfiguration, Predicate<GeneratorStatistics> writeLog) { return runGenerator(namedConfiguration, writeLog, false); } /** * Runs a generator and writes a log entry for the run. * * @param namedConfiguration Configuration for the generator * @param writeLog When this predicate evaluates to {@code true} a log entry is written (with {@link * LogEntryDAO}), if it evaluates to {@code false} the started log entry will be deleted. * @param writeLogLast If this flag is {@code true} the log entry is started only after the plugin was run (i.e. * the duration will not be correct but the AUTO_INCREMENT column in the DB will not be increased in case {@code * writeLog} evaluated to false.. * @return The statistics returned by the generator or {@link StatisticsConstants.ExecutionFailedStatistics} if * an exception was thrown by the generator. */ public LogEntry runGenerator(NamedConfiguration namedConfiguration, Predicate<GeneratorStatistics> writeLog, boolean writeLogLast) { Preconditions.checkNotNull(namedConfiguration); Preconditions.checkNotNull(namedConfiguration.getConfiguration()); Preconditions.checkNotNull(namedConfiguration.getName()); Preconditions.checkNotNull(namedConfiguration.getPluginId()); Preconditions.checkNotNull(writeLog); Generator<GeneratorConfiguration, GeneratorStatistics> generator = registry.getGenerators().get(namedConfiguration.getPluginId()); GeneratorConfiguration configuration = namedConfiguration.getConfiguration(); // is this needed? tenant should be set in the configuration stored in configuration.setTenantId(namedConfiguration.getTenantId()); generator.setConfiguration(configuration); LogEntry logEntry = new LogEntry(namedConfiguration.getTenantId(), namedConfiguration.getPluginId(), new Date(), namedConfiguration.getAssocTypeId(), configuration); GeneratorStatistics statistics; try { if (!writeLogLast) logEntryDAO.startEntry(logEntry); //switch classloader to the generator's own classloader so its exclusive classes are visible ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); ClassLoader generatorClassLoader = generator.getClass().getClassLoader(); Thread.currentThread().setContextClassLoader(generatorClassLoader); statistics = generator.execute(); Thread.currentThread().setContextClassLoader(currentClassLoader); } catch (Throwable e) { logger.error( String.format("Running plugin %s with configuration \"%s\" for tenant %d with assocType %d failed", namedConfiguration.getPluginId(), namedConfiguration.getName(), namedConfiguration.getTenantId(), namedConfiguration.getAssocTypeId()), e); statistics = new StatisticsConstants.ExecutionFailedStatistics(e); } boolean doWriteLog = writeLog.apply(statistics); logEntry.setStatistics(statistics); logEntry.setEndDate(new Date()); if (doWriteLog) { if (writeLogLast) logEntryDAO.startEntry(logEntry); logEntryDAO.endEntry(logEntry); } else if (!writeLogLast) logEntryDAO.deleteEntry(logEntry); return logEntry; } public List<LogEntry> runGeneratorsForTenant(int tenantId) { return runGeneratorsForTenant(tenantId, Predicates.<GeneratorStatistics>alwaysTrue()); } public List<LogEntry> runGeneratorsForTenant(int tenantId, Predicate<GeneratorStatistics> writeLog) { return runGeneratorsForTenant(tenantId, writeLog, false); } public List<LogEntry> runGeneratorsForTenant(int tenantId, Predicate<GeneratorStatistics> writeLog, boolean writeLogLast) { Map<String, Integer> assocTypes = assocTypeDAO.getMapping(tenantId); List<LogEntry> result = Lists.newArrayList(); for (Integer assocTypeId : assocTypes.values()) { NamedConfiguration namedConfiguration = namedConfigurationDAO.readActiveConfiguration(tenantId, assocTypeId); if (namedConfiguration == null) continue; result.add(runGenerator(namedConfiguration, writeLog, writeLogLast)); } return result; } /* earlier draft private Map<String, Generator> generators; // // Cancels all planned Generator executions (if any) and re-schedules them. // public void reScheduleAllRuns() { // cancel all schedules if there are any // walk over all tenant configs // start scheduler } // // Cancels all planned Generator executions for the specified tenant (if // any) and re-schedules them. // // @param tenant // public void reScheduleTenantRuns(TenantVO tenant) { // cancel all timers for tenant // read configuration for tenant // create quartz triggers from the scheduling properties // create GeneratorTask instance // somehow pack this together into quarts job / jobInfo / trigger // add to scheduler } // // Cancels all planned Generator executions. // public void cancelAllRuns() { // just shut down the scheduler } public void cancelScheduledRunsForTenant(TenantVO tenant) { // walk over scheduled jobs, check if they // are meant for the specified tenant } */ }