/******************************************************************************* * Copyright (c) 2004, 2006 * Thomas Hallgren, Kenneth Olwing, Mitch Sonies * Pontus Rydin, Nils Unden, Peer Torngren * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the individual * copyright holders listed above, as Initial Contributors under such license. * The text of such license is available at www.eclipse.org. *******************************************************************************/ package org.eclipse.buckminster.manifest; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import org.eclipse.buckminster.core.helpers.FileUtils; import org.eclipse.buckminster.core.helpers.TextUtils; import org.eclipse.core.runtime.IProgressMonitor; public class Checksum implements Comparable<Checksum> { public static final Checksum[] EMPTY_LIST = new Checksum[0]; private static final String HEADER = "CHECKSUM:v0"; private static final String ALGORITHM_PREFIX = "ALGORITHM:"; private static final String ASSUMEDLINESEPARATOR_PREFIX = "ASSUMEDLINESEPARATOR:"; private static final String DIGEST_PREFIX = "DIGEST:"; private final byte[] m_digest; private final String m_algorithm; private final String m_assumedLineSeparator; public static Checksum fromBufferedReader(BufferedReader br) throws IOException, MissingDataException { String tmp; if (!br.readLine().equals(HEADER)) throw new MissingDataException("Missing header in persisted Checksum"); tmp = br.readLine(); if (!tmp.startsWith(ALGORITHM_PREFIX)) throw new MissingDataException("Missing algorithm in persisted Checksum"); String algorithm = tmp.substring(ALGORITHM_PREFIX.length()); tmp = br.readLine(); if (!tmp.startsWith(ASSUMEDLINESEPARATOR_PREFIX)) throw new MissingDataException("Missing assumed line separator in persisted Checksum"); String assumedLineSeparator = new String(TextUtils.makeByteArrayFromHexString(tmp .substring(ASSUMEDLINESEPARATOR_PREFIX.length()))); tmp = br.readLine(); if (!tmp.startsWith(DIGEST_PREFIX)) throw new MissingDataException("Missing digest in persisted Checksum"); byte[] digest = TextUtils.makeByteArrayFromHexString(tmp.substring(DIGEST_PREFIX.length())); return new Checksum(digest, algorithm, assumedLineSeparator); } public Checksum(File path, IProgressMonitor monitor) throws IOException, NoSuchAlgorithmException { this(path, null, null, monitor); } public Checksum(File path, String algorithm, String assumedLineSeparator, IProgressMonitor monitor) throws IOException, NoSuchAlgorithmException { if (algorithm == null) algorithm = Constants.DEFAULT_ALGORITHM; if (assumedLineSeparator == null) assumedLineSeparator = Constants.LOCAL_LINESEPARATOR; m_digest = FileUtils.calculateDigest(path, algorithm, monitor); m_algorithm = algorithm; m_assumedLineSeparator = assumedLineSeparator; } /** * Only intended for internal use when reading a persisted manifest * * @param name * @param checksums * @throws Exception */ /* package */Checksum(byte[] digest, String algorithm, String assumedLineSeparator) { m_digest = new byte[digest.length]; System.arraycopy(digest, 0, m_digest, 0, digest.length); m_algorithm = algorithm; m_assumedLineSeparator = assumedLineSeparator; } public byte[] getBytes() { return m_digest; } public String getAlgorithm() { return m_algorithm; } public String getAssumedLineSeparator() { return m_assumedLineSeparator; } @Override public String toString() { StringBuilder sb = new StringBuilder(m_algorithm); sb.append(':'); sb.append(TextUtils.makeHexString(m_assumedLineSeparator.getBytes())); sb.append(':'); sb.append(TextUtils.makeHexString(m_digest)); return sb.toString(); } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Checksum)) return false; Checksum that = (Checksum)o; if (!this.m_algorithm.equals(that.m_algorithm)) return false; if (!this.m_assumedLineSeparator.equals(that.m_assumedLineSeparator)) return false; if(!Arrays.equals(this.m_digest, that.m_digest)) return false; return true; } @Override public int hashCode() { int result = 17; result = 37 * result + this.m_algorithm.hashCode(); result = 37 * result + this.m_assumedLineSeparator.hashCode(); result = 37 * result + Arrays.hashCode(this.m_digest); return result; } public int compareTo(Checksum that) { if (that == this) return 0; int v = this.m_algorithm.compareTo(that.m_algorithm); if (v != 0) return v; v = this.m_assumedLineSeparator.compareTo(that.m_assumedLineSeparator); if (v != 0) return v; if (Arrays.equals(this.m_digest, that.m_digest)) return 0; assert this.m_digest.length == that.m_digest.length : "Digest size difference"; int i = 0; while (i < this.m_digest.length) { if (this.m_digest[i] != that.m_digest[i]) return (this.m_digest[i] > that.m_digest[i]) ? 1 : -1; i++; } throw new InternalError(); } public void toPrintWriter(PrintWriter pw) { pw.println(HEADER); pw.print(ALGORITHM_PREFIX); pw.println(m_algorithm); pw.print(ASSUMEDLINESEPARATOR_PREFIX); pw.println(TextUtils.makeHexString(m_assumedLineSeparator.getBytes())); pw.print(DIGEST_PREFIX); pw.println(TextUtils.makeHexString(m_digest)); } }