package net.sourceforge.cruisecontrol.sourcecontrols; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import net.sourceforge.cruisecontrol.CruiseControlException; import net.sourceforge.cruisecontrol.Modification; import net.sourceforge.cruisecontrol.SourceControl; public class Veto implements SourceControl { /** * enable logging for this class */ private static final Logger LOG = Logger.getLogger(Veto.class); private Triggers triggers; private BuildStatus buildStatus; public List<Modification> getModifications(final Date lastBuild, final Date now) { final List<Modification> triggerMods = triggers.getModifications(lastBuild, now); if (triggerMods.isEmpty()) { return Collections.emptyList(); } final List<Modification> buildStatusMods = buildStatus.getModifications(lastBuild, now); if (buildStatusMods.isEmpty()) { throw new OutOfDateException("trigger changes with no buildstatus changes"); } final Modification latestBuildStatusMod = getLatestModification(buildStatusMods); if (!getNewerModifications(triggerMods, latestBuildStatusMod).isEmpty()) { throw new OutOfDateException("buildstatus out of date compared to trigger changes"); } return Collections.emptyList(); } private Modification getLatestModification(final List<Modification> mods) { Modification latest = null; for (final Modification mod : mods) { if (latest == null || mod.modifiedTime.after(latest.modifiedTime)) { latest = mod; } } return latest; } private List getNewerModifications(final List<Modification> mods, final Modification buildStatusMod) { List<Modification> newerMods = new ArrayList<Modification>(); LOG.debug("Comparing all trigger mods against buildStatusMod with date [" + buildStatusMod.modifiedTime + "]"); for (final Modification mod : mods) { if (mod.modifiedTime.after(buildStatusMod.modifiedTime)) { newerMods.add(mod); LOG.debug("Newer file : " + mod.getFullPath() + " at [" + mod.modifiedTime + "]"); } } if (!newerMods.isEmpty()) { LOG.info("Found " + newerMods.size() + " modifications since last build status."); } return newerMods; } public Map<String, String> getProperties() { return Collections.emptyMap(); } public void validate() throws CruiseControlException { if (triggers == null) { throw new CruiseControlException("veto requires nested triggers element"); } triggers.validate(); if (buildStatus == null) { throw new CruiseControlException("veto requires a nested buildstatus element"); } buildStatus.validate(); } public Triggers createTriggers() throws CruiseControlException { if (triggers != null) { throw new CruiseControlException("only one nested triggers allowed"); } triggers = new Triggers(this); return triggers; } public BuildStatus createBuildStatus() throws CruiseControlException { if (buildStatus != null) { throw new CruiseControlException("only one nested buildstatus allowed"); } buildStatus = getBuildStatus(); return buildStatus; } protected BuildStatus getBuildStatus() { return new BuildStatus(); } private class OutOfDateException extends RuntimeException { public OutOfDateException(final String string) { super(string); } } }