/* __ *\ ** ________ ___ / / ___ Scala Ant Tasks ** ** / __/ __// _ | / / / _ | (c) 2005-2009, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ // $Id: Same.scala 16893 2009-01-13 13:09:22Z cunei $ package scala.tools.ant import java.io.{File, FileInputStream} import org.apache.tools.ant.{BuildException, Project} import org.apache.tools.ant.taskdefs.MatchingTask import org.apache.tools.ant.util.FileUtils import org.apache.tools.ant.util.{FileNameMapper, IdentityMapper} import org.apache.tools.ant.types.Mapper /** <p> * An Ant task that, for a set of files, tests them for byte-to-byte * equality with one or more other files. * This task supports the following parameters as attributes: * </p><ul> * <li>dir</li> * <li>todir</li> * <li>resultproperty (a property to be set when all tested files pairs are equal, if not set, the task will fail instead),</li> * <li>failing (whether to stop if all files are not equal).</li></ul> * <p>It also support the following nested elements:</p><ul> * <li>mapper (a mapper from original files to test files).</li></ul> * <p>This task itself defines a fileset that represents the set of original files.</p> * * @author Gilles Dubochet * @version 1.0 */ class Same extends MatchingTask { /** The unique Ant file utilities instance to use in this task. */ private val fileUtils = FileUtils.newFileUtils() /*============================================================================*\ ** Ant user-properties ** \*============================================================================*/ private var origin: Option[File] = None private var destination: Option[File] = None private var resultProperty: Option[String] = None private var failing: Boolean = false private var mapperElement: Option[Mapper] = None /*============================================================================*\ ** Properties setters ** \*============================================================================*/ def setDir(input: File) = origin = Some(input) def setTodir(input: File) = destination = Some(input) def setResultproperty(input: String) = resultProperty = Some(input) def setFailondifferent(input: Boolean) = failing = input def createMapper(): Mapper = if (mapperElement.isEmpty) { val mapper = new Mapper(getProject) mapperElement = Some(mapper) mapper } else throw new BuildException("Cannot define more than one mapper", getLocation) def add(fileNameMapper: FileNameMapper) = createMapper().add(fileNameMapper) /*============================================================================*\ ** Properties getters ** \*============================================================================*/ private def getMapper: FileNameMapper = mapperElement match { case None => new IdentityMapper() case Some(me) => me.getImplementation } /*============================================================================*\ ** Support methods ** \*============================================================================*/ private var allEqualNow = true /** Tests if all mandatory attributes are set and valid. */ private def validateAttributes = { if (origin.isEmpty) error("Mandatory attribute 'dir' is not set.") if (destination.isEmpty) error("Mandatory attribute 'todir' is not set.") } private def reportDiff(f1: File, f2: File) = { allEqualNow = false log("File '" + f1 + "' is different from correspondant.") } private def reportMissing(f1: File) = { allEqualNow = false log("File '" + f1 + "' has no correspondant.") } /*============================================================================*\ ** The big execute method ** \*============================================================================*/ override def execute() = { validateAttributes val mapper = getMapper allEqualNow = true val originNames: Array[String] = getDirectoryScanner(origin.get).getIncludedFiles val bufferSize = 1024 val originBuffer = new Array[Byte](bufferSize) val destBuffer = new Array[Byte](bufferSize) for ( originName: String <- originNames; destName: String <- mapper.mapFileName(originName) ) { //println("originName="+originName) //println("destName ="+destName) var equalNow = true val originFile = new File(origin.get, originName) val destFile = new File(destination.get, destName) if (originFile.canRead && destFile.canRead) { val originStream = new FileInputStream(originFile) val destStream = new FileInputStream(destFile) var originRemaining = originStream.read(originBuffer) var destRemaining = destStream.read(destBuffer) while (originRemaining > 0 && equalNow) { if (originRemaining == destRemaining) for (idx <- 0 until originRemaining) equalNow = equalNow && (originBuffer(idx) == destBuffer(idx)) else equalNow = false originRemaining = originStream.read(originBuffer) destRemaining = destStream.read(destBuffer) } if (destRemaining > 0) equalNow = false if (!equalNow) reportDiff(originFile, destFile) originStream.close destStream.close } else reportMissing(originFile) } if (!allEqualNow) if (failing) error("There were differences between '" + origin.get + "' and '" + destination.get + "'") else log("There were differences between '" + origin.get + "' and '" + destination.get + "'") else { if (!resultProperty.isEmpty) getProject.setProperty(resultProperty.get, "yes") log("All files in '" + origin.get + "' and '" + destination.get + "' are equal", Project.MSG_VERBOSE) } } }