package net.sourceforge.cruisecontrol.sourcecontrols;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import net.sourceforge.cruisecontrol.CruiseControlConfig;
import net.sourceforge.cruisecontrol.CruiseControlException;
import net.sourceforge.cruisecontrol.Modification;
import net.sourceforge.cruisecontrol.ProjectQuery;
import net.sourceforge.cruisecontrol.gendoc.annotations.Default;
import net.sourceforge.cruisecontrol.gendoc.annotations.Description;
import net.sourceforge.cruisecontrol.gendoc.annotations.DescriptionFile;
import net.sourceforge.cruisecontrol.gendoc.annotations.Optional;
import net.sourceforge.cruisecontrol.gendoc.annotations.Required;
import net.sourceforge.cruisecontrol.util.ValidationHelper;
import org.apache.log4j.Logger;
/**
* Modifi TOD: DOPSAT!!!
* @author dtihelka
*/
@DescriptionFile
public class ProjectStatus extends FakeUserSourceControl {
private static final long serialVersionUID = 5158569043922879751L;
private static final Logger LOG = Logger.getLogger(ProjectStatus.class);
/* All 4 copied from BuildStatus#getModifications() */
public static final String MOST_RECENT_LOGDIR_KEY = "most.recent.logdir";
public static final String MOST_RECENT_LOGFILE_KEY = "most.recent.logfile";
public static final String MOST_RECENT_LOGTIME_KEY = "most.recent.logtime";
public static final String MOST_RECENT_LOGLABEL_KEY = "most.recent.loglabel";
/** Data get by {@link #getProperties()} */
private final SourceControlProperties properties = new SourceControlProperties();
/** Value set through {@link #setVetoIfModified(boolean)} */
private boolean vetoIfMdified = false;
/** Value set through {@link #setTriggerOnSuccess(boolean)} */
private boolean triggerOnSuccess = true;
/** Value set through {@link #setProject(String)} */
private String projectName;
/** Interface to the project to be monitored */
private ProjectQuery project;
@Override
public Map<String, String> getProperties() {
return properties.getPropertiesAndReset();
}
@Override
@Description("Will set this property to 'true' if a modification has occurred. For use in conditionally "
+ "controlling the build later.")
@Optional
public void setProperty(String propertyName) {
properties.assignPropertyName(propertyName);
}
@SuppressWarnings("javadoc")
@Description("The name of project to be monitored.")
@Required
public void setProject(String name) {
projectName = name;
}
@SuppressWarnings("javadoc")
@Description("When set to <i>true</i>, the veto of build is signalized when a modificationis found "
+ "in the monitored project")
@Optional
@Default("false")
public void setVetoIfModified(boolean val) {
vetoIfMdified = val;
}
@SuppressWarnings("javadoc")
@Description("When set to <i>false</i>, the module will never trigger any build, no matterthe monitored "
+ "project is triggered. However, the veto of the build can still besignalized, if configured so.")
@Optional
@Default("true")
public void setTriggerOnSuccess(boolean val) {
triggerOnSuccess = val;
}
@Override
public void validate() throws CruiseControlException {
/* Project name is required */
ValidationHelper.assertIsSet(projectName, "project", getClass());
/* Get the project and check if exists */
project = CruiseControlConfig.findProject(projectName);
ValidationHelper.assertTrue(projectName.equals(project.getName()), "Mismatch in project names, want "
+ projectName + ", get " + project.getName());
}
@Override
public List<Modification> getModifications(Date lastBuild, Date now) {
final List<Modification> modifications = new ArrayList<Modification>();
final List<Modification> projModifs = project.modificationsSinceLastBuild();
final Date lastSuccess = project.successLastBuild();
/* There are modification in the monitored project since its last build. So, veto the build,
* if any of the modifications is more recent than the lastBuild value of this project */
if (vetoIfMdified && !projModifs.isEmpty()) {
for (Modification mod : projModifs) {
if (mod.getModifiedTime().after(lastBuild)) {
throw new ProjectStatus.VetoException("Modifications in " + project.getName()
+ " found since its build on " + lastSuccess);
}
}
}
/* If the last successful build of the monitored project is more recent than the last build of the
* current project, and the build is required to be triggered, fill the list of modifications in
* the monitored project occurred since the last build of this project. */
if (lastSuccess.after(lastBuild) && triggerOnSuccess) {
final Modification summary = new Modification("buildstatus");
final Date modifiedTime = project.successLastBuild();
final String revision = project.successLastLabel();
summary.comment = "Summary since the last successfull build of " + project.getName();
summary.modifiedTime = modifiedTime;
summary.revision = revision;
modifications.add(summary);
modifications.addAll(project.modificationsSince(lastBuild));
modifications.addAll(projModifs);
Date lastModif = new Date();
for (Modification mod : projModifs) {
if (lastModif.before(mod.getModifiedTime())) {
lastModif = mod.getModifiedTime();
}
}
/* Fill properties, Code copied from BuildStatus#getModifications() */
properties.put("most.recent.logdir", project.getLogDir());
properties.put("most.recent.logfile", project.successLastLog());
properties.put("most.recent.logtime", new SimpleDateFormat("yyyyMMddHHmmss").format(modifiedTime));
properties.put("most.recent.loglabel", revision);
}
return finalizeModifications(modifications);
}
/**
* Calls {@link SourceControlProperties#modificationFound()} is a modification has been found.
* @param modifications the list of modifications found
* @return modifications array back (unchanged)
*/
private List<Modification> finalizeModifications(List<Modification> modifications) {
if (!modifications.isEmpty()) {
properties.modificationFound();
}
return modifications;
}
/** Exception thrown o signalize the cancel of the build */
private class VetoException extends RuntimeException {
@SuppressWarnings("javadoc")
public VetoException(String message) {
super(message);
}
/** Setialzation UID */
private static final long serialVersionUID = 1L;
}
}