/******************************************************************************** * CruiseControl, a Continuous Integration Toolkit * Copyright (c) 2004, ThoughtWorks, Inc. * 200 E. Randolph, 25th Floor * Chicago, IL 60601 USA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * + Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * + Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the * names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************************/ package net.sourceforge.cruisecontrol; import java.io.File; import java.io.Serializable; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import net.sourceforge.cruisecontrol.taglib.CruiseControlLogFileFilter; import net.sourceforge.cruisecontrol.taglib.CruiseControlSuccessfulLogFileFilter; /** * Contains various information about a specific build. The * information is extracted from the name of the log file * generated by the build. * * @author <a href="mailto:robertdw@users.sourceforge.net">Robert Watkins</a> * @author <a href="mailto:hak@2mba.dk">Hack Kampbjorn</a> */ public class BuildInfo implements Comparable<BuildInfo>, Serializable { private static final long serialVersionUID = 5896165618310498253L; public static final String LOG_PREFIX = "log"; public static final char LABEL_SEPARATOR = 'L'; public static final String LOG_DATE_PATTERN = "yyyyMMddHHmmss"; private final Date buildDate; private final String dateStamp; private final String label; private final LogFile logFile; // Convenience constructor used by the testcasess BuildInfo(String infoText) throws ParseException { this(new File(infoText)); } public BuildInfo(File logFile) throws ParseException { this(new LogFile(logFile)); } public BuildInfo(LogFile logFile) throws ParseException { this.logFile = logFile; dateStamp = deriveDateStamp(); buildDate = deriveDate(); label = deriveLabel(); } private String deriveLabel() { String infoText = logFile.getName(); boolean buildSuccessful = new CruiseControlSuccessfulLogFileFilter().isSuccessful(infoText); String theLabel; if (buildSuccessful) { int labelStartIndex = (LOG_PREFIX + LOG_DATE_PATTERN + LABEL_SEPARATOR).length(); theLabel = infoText.substring(labelStartIndex); } else { theLabel = null; } return theLabel; } private String deriveDateStamp() throws ParseException { String infoText = logFile.getName(); try { return infoText.substring(LOG_PREFIX.length(), LOG_PREFIX.length() + LOG_DATE_PATTERN.length()); } catch (StringIndexOutOfBoundsException e) { throw new IllegalStateException("infoText has wrong format: " + infoText + " " + e.getMessage()); } } private Date deriveDate() throws ParseException { String infoText = logFile.getName(); Date theDate; final DateFormat logDateFormat = new SimpleDateFormat(LOG_DATE_PATTERN); try { theDate = logDateFormat.parse(dateStamp); } catch (ParseException e) { throw new ParseException("Invalid format: " + infoText + ". Format must be logyyyyMMddHHmmSS.xml or " + "logyyyyMMddHHmmSSLlabel.xml", e.getErrorOffset()); } return theDate; } public Date getBuildDate() { return buildDate; } /** * Gets the date stamp of the log name. * @return the build date as a stamp. */ public String getDateStamp() { return dateStamp; } public String getLabel() { return label; } public boolean isSuccessful() { return getLabel() != null; } /** * @return the log's name with a file extension. */ public String getLogName() { return logFile.getName(); } public LogFile getLogFile() { return logFile; } public static BuildInfoSummary loadFromDir(final File logDir) throws CruiseControlWebAppException { final File[] logFileNames = logDir.listFiles(new CruiseControlLogFileFilter()); if (logFileNames == null) { throw new CruiseControlWebAppException("Could not access the directory " + logDir.getAbsolutePath()); } else if (logFileNames.length == 0) { throw new CruiseControlWebAppException("Configuration problem? No logs found in logDir: " + logDir.getAbsolutePath()); } final List<BuildInfo> buildInfoList = new ArrayList<BuildInfo>(logFileNames.length); for (final File file : logFileNames) { try { buildInfoList.add(new BuildInfo(file)); } catch (ParseException e) { throw new CruiseControlWebAppException("Could not parse log file name " + file.getName() + ". Is the filter broken?", e); } } Collections.sort(buildInfoList); return new BuildInfoSummary(buildInfoList); } /** * Return a comparison based on the build time. * @see java.lang.Comparable#compareTo(java.lang.Object) */ public int compareTo(final BuildInfo other) { return this.buildDate.compareTo(other.buildDate); } }