001: package net.sourceforge.cruisecontrol.sourcecontrols;
002:
003: import java.util.ArrayList;
004: import java.util.Collections;
005: import java.util.Date;
006: import java.util.Iterator;
007: import java.util.List;
008: import java.util.Map;
009:
010: import org.apache.log4j.Logger;
011:
012: import net.sourceforge.cruisecontrol.CruiseControlException;
013: import net.sourceforge.cruisecontrol.Modification;
014: import net.sourceforge.cruisecontrol.SourceControl;
015:
016: public class Veto implements SourceControl {
017: /**
018: * enable logging for this class
019: */
020: private static Logger log = Logger.getLogger(Veto.class);
021:
022: private Triggers triggers;
023:
024: private BuildStatus buildStatus;
025:
026: public List getModifications(Date lastBuild, Date now) {
027:
028: List triggerMods = triggers.getModifications(lastBuild, now);
029: if (triggerMods.isEmpty()) {
030: return Collections.EMPTY_LIST;
031: }
032:
033: List buildStatusMods = buildStatus.getModifications(lastBuild,
034: now);
035: if (buildStatusMods.isEmpty()) {
036: throw new OutOfDateException(
037: "trigger changes with no buildstatus changes");
038: }
039:
040: Modification latestBuildStatusMod = getLatestModification(buildStatusMods);
041: Modification latestTriggerMod = getLatestModification(triggerMods);
042:
043: if (!getNewerModifications(triggerMods, latestBuildStatusMod)
044: .isEmpty()) {
045: throw new OutOfDateException(
046: "buildstatus out of date compared to trigger changes");
047: }
048:
049: return Collections.EMPTY_LIST;
050: }
051:
052: private Modification getLatestModification(List mods) {
053: Modification latest = null;
054: for (Iterator iter = mods.iterator(); iter.hasNext();) {
055: Modification mod = (Modification) iter.next();
056: if (latest == null
057: || mod.modifiedTime.after(latest.modifiedTime)) {
058: latest = mod;
059: }
060: }
061: return latest;
062: }
063:
064: private List getNewerModifications(List mods,
065: Modification buildStatusMod) {
066: List newerMods = new ArrayList();
067: log
068: .info("Comparing all trigger mods against buildStatusMod with date ["
069: + buildStatusMod.modifiedTime + "]");
070: for (Iterator iter = mods.iterator(); iter.hasNext();) {
071: Modification mod = (Modification) iter.next();
072: if (mod.modifiedTime.after(buildStatusMod.modifiedTime)) {
073: newerMods.add(mod);
074: log.info("Newer file : " + mod.getFullPath() + " at ["
075: + mod.modifiedTime + "]");
076: }
077: }
078: return newerMods;
079: }
080:
081: public Map getProperties() {
082: return Collections.EMPTY_MAP;
083: }
084:
085: public void validate() throws CruiseControlException {
086: if (triggers == null) {
087: throw new CruiseControlException(
088: "veto requires nested triggers element");
089: }
090: triggers.validate();
091: if (buildStatus == null) {
092: throw new CruiseControlException(
093: "veto requires a nested buildstatus element");
094: }
095: buildStatus.validate();
096: }
097:
098: public Triggers createTriggers() throws CruiseControlException {
099: if (triggers != null) {
100: throw new CruiseControlException(
101: "only one nested triggers allowed");
102: }
103: triggers = new Triggers(this );
104: return triggers;
105: }
106:
107: public BuildStatus createBuildStatus()
108: throws CruiseControlException {
109: if (buildStatus != null) {
110: throw new CruiseControlException(
111: "only one nested buildstatus allowed");
112: }
113: buildStatus = getBuildStatus();
114: return buildStatus;
115: }
116:
117: protected BuildStatus getBuildStatus() {
118: return new BuildStatus();
119: }
120:
121: private class OutOfDateException extends RuntimeException {
122:
123: public OutOfDateException(String string) {
124: super(string);
125: }
126: }
127:
128: }
|