io.milton.zsync.Generator Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* Generator: Checksum generation methods.
$Id: Generator.java,v 1.12 2003/07/20 04:26:13 rsdio Exp $
Copyright (C) 2003 Casey Marshall
Copyright (C) 2011 Tomas Hlavnicka
*
This file is a part of Jarsync.
Jarsync is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
Jarsync is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jarsync; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place, Suite 330,
Boston, MA 02111-1307
USA
Linking Jarsync statically or dynamically with other modules is
making a combined work based on Jarsync. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination. */
package io.milton.zsync;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Checksum generation methods.
*
* @version $Revision: 1.12 $
*/
public class Generator {
public Generator() {
}
/**
* Generate checksums over an entire byte array, with a specified
* base offset. This baseOffset
is added to the offset
* stored in each {@link ChecksumPair}.
*
* @param buf The byte array to checksum.
* @param baseOffset The offset from whence this byte array came.
* @return A {@link java.util.List} of {@link ChecksumPair}s
* generated from the array.
* @see #generateSums(byte[],int,int,long)
*/
public List generateSums(byte[] buf, long baseOffset, Configuration config) {
return generateSums(buf, 0, buf.length, baseOffset, config);
}
/**
* Generate checksums over a portion of abyte array, with a specified
* base offset. This baseOffset
is added to the offset
* stored in each {@link ChecksumPair}.
*
* @param buf The byte array to checksum.
* @param off From whence in buf
to start.
* @param len The number of bytes to check in
* buf
.
* @param baseOffset The offset from whence this byte array came.
* @return A {@link java.util.List} of {@link ChecksumPair}s
* generated from the array.
*/
private List generateSums(byte[] buf, int off, int len, long baseOffset, Configuration config) {
int count = (len + (config.blockLength - 1)) / config.blockLength;
int remainder = len % config.blockLength;
int offset = off;
List sums = new ArrayList(count);
for (int i = 0; i < count; i++) {
int n = Math.min(len, config.blockLength);
ChecksumPair pair = generateSum(buf, offset, n, offset + baseOffset, config);
pair.seq = i;
sums.add(pair);
len -= n;
offset += n;
}
return sums;
}
/**
* Generate checksums for an entire file.
*
* @param f The {@link java.io.File} to checksum.
* @return A {@link java.util.List} of {@link ChecksumPair}s
* generated from the file.
* @throws java.io.IOException if f
cannot be read from.
*/
public List generateSums(File f, Configuration config) throws IOException {
long len = f.length();
int count = (int) ((len + (config.blockLength + 1)) / config.blockLength);
long offset = 0;
FileInputStream fin = new FileInputStream(f);
List sums = new ArrayList(count);
int n = config.blockLength;
byte[] buf = new byte[n];
for (int i = 0; i < count; i++) {
int l = fin.read(buf, 0, n);
if (l == -1) {
break;
}
/*
* V pripade, ze mnozstvi dat nevyplni celou blocksize, vyplnime
* nezaplnene misto v bufferu nulami
*/
if (n < config.blockLength) {
Arrays.fill(buf, n, config.blockLength, (byte) 0);
}
/* spocita sumy pouze pokud je mnozstvi dat vetsi nez 0,
* a spocita je pro cely blok velikosti blocksize
* data, ktera nevyplnila celou blocksize jsou doplnena nulami
* do velikosti blocksize.
*/
if (l > 0) {
ChecksumPair pair = generateSum(buf, 0, config.blockLength /* not in zsync -> Math.min(l, n)*/, offset, config);
pair.seq = i;
sums.add(pair);
len -= n;
offset += n;
n = (int) Math.min(len, config.blockLength);
}
}
fin.close();
return sums;
}
/**
* Generate checksums for an InputStream.
*
* @param in The {@link java.io.InputStream} to checksum.
* @return A {@link java.util.List} of {@link ChecksumPair}s
* generated from the bytes read.
* @throws java.io.IOException if reading fails.
*/
public List generateSums(InputStream in, Configuration config, MessageDigest sha1) throws IOException, NoSuchAlgorithmException {
List sums = null;
byte[] buf = new byte[config.blockLength * config.blockLength];
long offset = 0;
int len = 0;
while ((len = in.read(buf)) != -1) {
sha1.update(buf, 0, len);
if (sums == null) {
sums = generateSums(buf, 0, len, offset, config);
} else {
sums.addAll(generateSums(buf, 0, len, offset, config));
}
offset += len;
}
return sums;
}
/**
* Generate a sum pair for an entire byte array.
*
* @param buf The byte array to checksum.
* @param fileOffset The offset in the original file from whence
* this block came.
* @return A {@link ChecksumPair} for this byte array.
*/
public ChecksumPair generateSum(byte[] buf, long fileOffset, Configuration config) {
return generateSum(buf, 0, buf.length, fileOffset, config);
}
/**
* Generate a sum pair for a portion of a byte array.
*
* @param buf The byte array to checksum.
* @param off Where in buf
to start.
* @param len How many bytes to checksum.
* @param fileOffset The original offset of this byte array.
* @return A {@link ChecksumPair} for this byte array.
*/
public ChecksumPair generateSum(byte[] buf, int off, int len, long fileOffset, Configuration config) {
ChecksumPair p = new ChecksumPair();
config.weakSum.check(buf, off, len);
config.strongSum.update(buf, off, len);
if (config.checksumSeed != null) {
config.strongSum.update(config.checksumSeed, 0,
config.checksumSeed.length);
}
p.weak = config.weakSum.getValue();
p.strong = new byte[config.strongSumLength];
System.arraycopy(config.strongSum.digest(), 0, p.strong, 0,
p.strong.length);
p.offset = fileOffset;
p.length = len;
return p;
}
public int generateWeakSum(byte[] buf, int offset, Configuration config) {
config.weakSum.first(buf, offset, config.blockLength);
return config.weakSum.getValue();
}
public int generateRollSum(byte b, Configuration config) {
config.weakSum.roll(b);
return config.weakSum.getValue();
}
public byte[] generateStrongSum(byte[] buf, int off, int len, Configuration config) {
config.strongSum.update(buf, off, len);
byte[] strongSum = new byte[config.strongSumLength];
System.arraycopy(config.strongSum.digest(), 0, strongSum, 0, strongSum.length);
return strongSum;
}
}