at.spardat.xma.boot.transform.HashChecksum Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* s IT Solutions AT Spardat GmbH - initial API and implementation
*******************************************************************************/
/*
* @(#) $Id: HashChecksum.java 2084 2007-11-27 14:53:31Z s3460 $
*/
package at.spardat.xma.boot.transform;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import at.spardat.xma.boot.logger.LogLevel;
import at.spardat.xma.boot.logger.Logger;
import at.spardat.xma.boot.util.Util;
/**
* Class for calculation checksum values for jar-files and plain files.
* For jar-files a MD5-hash is calculated over the contents of all files contained in
* the jar-file. Only the contents of the files determine the hash value, their names,
* timestamps etc. do not influence the hash value.
* For plain files (text files, native libs, etc.) a MD5-hash is clalculated over the content
* of the file.
* @author s2877
* @since 1.3.0
*/
public class HashChecksum {
/**
* Size of the read buffer to use.
*/
private static int readBufferSize = 8 * 1024;
/**
* Calculates the hasvalue for jar-files. It is calculated over all contained
* files. The order of the files in the jar-file is significant. The timestamps of the files
* do not influence the hash value.
* @param file the jar-file to calculate the hash value for.
* @return the calculated checksum
* @throws IOException on errors reading the file
*/
public static String calcJarCheckSum(File file) throws IOException {
MessageDigest messageDigest;
byte[] buf = new byte[readBufferSize];
JarFile jarfile = null;
try {
jarfile = new JarFile(file);
try {
messageDigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException noalgo) {
throw new RuntimeException(noalgo);
}
for (Enumeration e = jarfile.entries() ; e.hasMoreElements() ;) {
JarEntry entry = (JarEntry)e.nextElement();
if(!entry.isDirectory() && !"META-INF/MANIFEST.MF".equalsIgnoreCase(entry.getName()) ) {
// if(verbose) System.out.println( "element: " + entry.getName() );
InputStream is = jarfile.getInputStream( entry );
DigestInputStream dis = new DigestInputStream(is, messageDigest);
while (dis.read(buf, 0, readBufferSize) != -1) {
;
}
dis.close();
is.close();
} // end if not directory
}
} finally {
try {
if(jarfile!=null) jarfile.close();
} catch (Exception ex) {
Logger.getLogger("bootrt.bootRuntime").log(LogLevel.WARNING,"error closing "+file.getAbsolutePath(),ex);
}
}
byte[] fileDigest = messageDigest.digest ();
return toHexString(fileDigest);
}
/**
* Calculates the hashvalue for a plain file or a native lib. The binary content of the
* file is hashed. Every change to the file content leads to a change in the resulting hash value.
* @param file the jar-file to calculate the hash value for.
* @return the calculated checksum
* @throws IOException on errors reading the file
* @since 1.3.0
* @author s2877
*/
public static String calcFileCheckSum(File file) throws IOException {
MessageDigest messageDigest;
InputStream is = null;
DigestInputStream dis = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
is = new FileInputStream(file);
dis = new DigestInputStream(is, messageDigest);
byte[] buf = new byte[readBufferSize];
while(dis.read(buf, 0, readBufferSize)>0);
return toHexString(messageDigest.digest());
} catch (NoSuchAlgorithmException noalgo) {
throw new RuntimeException(noalgo);
} finally {
Util.close(dis,"digest input stream on "+file.getAbsolutePath());
Util.close(is,file.getAbsolutePath());
}
}
/**
* Calculates the hashvalue over the content of a plain file or a native lib.
* Every change to the given data leads to a change in the resulting hash value.
* @param data the bytes over which to caluclate the checksum
* @return the calculated checksum
* @since 1.3.0
* @author s2877
*/
public static String calcCheckSum(byte[] data) {
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(data);
return toHexString(messageDigest.digest());
} catch (NoSuchAlgorithmException noalgo) {
throw new RuntimeException(noalgo);
}
}
/**
* Converts the given binary data int a hexadezimal string representation.
* @param data to convert
* @return the converted data
* @since 1.3.0
* @author s2877
*/
public static String toHexString(byte[] data) {
StringBuffer checksumSb = new StringBuffer();
for (int i = 0; i < data.length; i++) {
String hexStr = Integer.toHexString(0x00ff & data[i]);
if (hexStr.length() < 2) {
checksumSb.append("0");
}
checksumSb.append(hexStr);
}
return checksumSb.toString();
}
/**
* Compare two application descriptor hash codes
* @return true if both byte arrays contain the same sequence of bytes
* false otherwise
*/
public static boolean areEqual( byte[] a, byte[] b ) {
if( a==null || b==null || a.length != b.length) {
return false;
}
for( int i=0; i