@@ -34,12 +34,16 @@ import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Set;
import java.util.Arrays;
import java.text.MessageFormat;
import java.text.ParseException;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.condition.Condition;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.util.StringUtils;
/**
* Used to create or verify file checksums.
@@ -126,6 +130,11 @@ public class Checksum extends MatchingTask implements Condition {
*/
private int readBufferSize = 8 * 1024;
/**
* Formater for the checksum file.
*/
private MessageFormat format = FormatElement.getDefault().getFormat();
/**
* Sets the file for which the checksum is to be calculated.
*/
@@ -208,6 +217,26 @@ public class Checksum extends MatchingTask implements Condition {
this.readBufferSize = size;
}
/**
* Select the in/output pattern via a well know format name.
*
* @since 1.7.0
*/
public void setFormat(FormatElement e) {
format = e.getFormat();
}
/**
* Specify the pattern to use as a MessageFormat pattern.
*
* <p>{0} gets replaced by the checksum, {1} by the filename.</p>
*
* @since 1.7.0
*/
public void setPattern(String p) {
format = new MessageFormat(p);
}
/**
* Files to generate checksums for.
*/
@@ -223,7 +252,7 @@ public class Checksum extends MatchingTask implements Condition {
boolean value = validateAndExecute();
if (verifyProperty != null) {
getProject().setNewProperty(verifyProperty,
new Boolean(value).toString());
new Boolean(value).toString());
}
}
@@ -246,39 +275,39 @@ public class Checksum extends MatchingTask implements Condition {
if (file == null && filesets.size() == 0) {
throw new BuildException(
"Specify at least one source - a file or a fileset.");
"Specify at least one source - a file or a fileset.");
}
if (file != null && file.exists() && file.isDirectory()) {
throw new BuildException(
"Checksum cannot be generated for directories");
"Checksum cannot be generated for directories");
}
if (file != null && totalproperty != null) {
throw new BuildException(
"File and Totalproperty cannot co-exist.");
"File and Totalproperty cannot co-exist.");
}
if (property != null && fileext != null) {
throw new BuildException(
"Property and FileExt cannot co-exist.");
"Property and FileExt cannot co-exist.");
}
if (property != null) {
if (forceOverwrite) {
throw new BuildException(
"ForceOverwrite cannot be used when Property is specified");
"ForceOverwrite cannot be used when Property is specified");
}
if (file != null) {
if (filesets.size() > 0) {
throw new BuildException("Multiple files cannot be used "
+ "when Property is specified");
+ "when Property is specified");
}
} else {
if (filesets.size() > 1) {
throw new BuildException("Multiple files cannot be used "
+ "when Property is specified");
+ "when Property is specified");
}
}
}
@@ -289,12 +318,12 @@ public class Checksum extends MatchingTask implements Condition {
if (verifyProperty != null && forceOverwrite) {
throw new BuildException(
"VerifyProperty and ForceOverwrite cannot co-exist.");
"VerifyProperty and ForceOverwrite cannot co-exist.");
}
if (isCondition && forceOverwrite) {
throw new BuildException("ForceOverwrite cannot be used when "
+ "conditions are being used.");
+ "conditions are being used.");
}
messageDigest = null;
@@ -323,7 +352,7 @@ public class Checksum extends MatchingTask implements Condition {
fileext = "." + algorithm;
} else if (fileext.trim().length() == 0) {
throw new BuildException(
"File extension when specified must not be an empty string");
"File extension when specified must not be an empty string");
}
try {
@@ -371,15 +400,7 @@ public class Checksum extends MatchingTask implements Condition {
Project.MSG_VERBOSE);
if (totalproperty != null) {
// Read the checksum from disk.
String checksum = null;
try {
BufferedReader diskChecksumReader
= new BufferedReader(new FileReader(checksumFile));
checksum = diskChecksumReader.readLine();
} catch (IOException e) {
throw new BuildException("Couldn't read checksum file "
+ checksumFile, e);
}
String checksum = readChecksum(checksumFile);
byte[] digest = decodeHex(checksum.toCharArray());
allDigests.put(file, digest);
}
@@ -389,8 +410,8 @@ public class Checksum extends MatchingTask implements Condition {
}
} else {
String message = "Could not find file "
+ file.getAbsolutePath()
+ " to generate checksum for.";
+ file.getAbsolutePath()
+ " to generate checksum for.";
log(message);
throw new BuildException(message, getLocation());
}
@@ -457,23 +478,26 @@ public class Checksum extends MatchingTask implements Condition {
if (isCondition) {
File existingFile = (File) destination;
if (existingFile.exists()) {
fis = new FileInputStream(existingFile);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String suppliedChecksum = br.readLine();
fis.close();
fis = null;
br.close();
isr.close();
checksumMatches = checksumMatches
&& checksum.equals(suppliedChecksum);
try {
String suppliedChecksum =
readChecksum(existingFile);
checksumMatches = checksumMatches
&& checksum.equals(suppliedChecksum);
} catch (BuildException be) {
// file is on wrong format, swallow
checksumMatches = false;
}
} else {
checksumMatches = false;
}
} else {
File dest = (File) destination;
fos = new FileOutputStream(dest);
fos.write(checksum.getBytes());
fos.write(format.format(new Object[] {
checksum,
src.getName(),
}).getBytes());
fos.write(StringUtils.LINE_SEP.getBytes());
fos.close();
fos = null;
}
@@ -562,4 +586,69 @@ public class Checksum extends MatchingTask implements Condition {
return out;
}
/**
* reads the checksum from a file using the specified format.
*
* @since 1.7
*/
private String readChecksum(File f) {
BufferedReader diskChecksumReader = null;
try {
diskChecksumReader = new BufferedReader(new FileReader(f));
Object[] result = format.parse(diskChecksumReader.readLine());
if (result == null || result.length == 0 || result[0] == null) {
throw new BuildException("failed to find a checksum");
}
return (String) result[0];
} catch (IOException e) {
throw new BuildException("Couldn't read checksum file " + f, e);
} catch (ParseException e) {
throw new BuildException("Couldn't read checksum file " + f, e);
} finally {
if (diskChecksumReader != null) {
try {
diskChecksumReader.close();
} catch (IOException e) {
// ignore
}
}
}
}
/**
* Helper class for the format attribute.
*
* @since 1.7
*/
public static class FormatElement extends EnumeratedAttribute {
private static HashMap formatMap = new HashMap();
private static final String CHECKSUM = "CHECKSUM";
private static final String MD5SUM = "MD5SUM";
private static final String SVF = "SVF";
static {
formatMap.put(CHECKSUM, new MessageFormat("{0}"));
formatMap.put(MD5SUM, new MessageFormat("{0} *{1}"));
formatMap.put(SVF, new MessageFormat("MD5 ({1}) = {0}"));
}
public FormatElement() {
super();
}
public static FormatElement getDefault() {
FormatElement e = new FormatElement();
e.setValue(CHECKSUM);
return e;
}
public MessageFormat getFormat() {
return (MessageFormat) formatMap.get(getValue());
}
public String[] getValues() {
return new String[] {CHECKSUM, MD5SUM, SVF};
}
}
}