001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.io.delta;
016    
017    import java.io.IOException;
018    
019    import java.nio.ByteBuffer;
020    import java.nio.channels.FileChannel;
021    import java.nio.channels.ReadableByteChannel;
022    import java.nio.channels.WritableByteChannel;
023    
024    /**
025     * @author Connor McKay
026     */
027    public class DeltaUtil {
028    
029            public static final int BUFFER_FACTOR = 16;
030    
031            public static final byte DATA_KEY = 1;
032    
033            public static final byte EOF_KEY = 0;
034    
035            public static final byte PROTOCOL_VERSION = 1;
036    
037            public static final byte REFERENCE_KEY = 2;
038    
039            public static final byte REFERENCE_RANGE_KEY = 3;
040    
041            public static void checksums(
042                            FileChannel originalFileChannel,
043                            ByteChannelWriter checksumsByteChannelWriter)
044                    throws IOException {
045    
046                    checksums(originalFileChannel, checksumsByteChannelWriter, 512);
047            }
048    
049            public static void checksums(
050                            FileChannel originalFileChannel,
051                            ByteChannelWriter checksumsByteChannelWriter, int blockLength)
052                    throws IOException {
053    
054                    RollingChecksum rollingChecksum = new RollingChecksum(
055                            originalFileChannel, blockLength);
056    
057                    checksumsByteChannelWriter.resizeBuffer(BUFFER_FACTOR * 20);
058    
059                    ByteBuffer byteBuffer = checksumsByteChannelWriter.getBuffer();
060    
061                    int blocksCount = (int)Math.ceil(
062                            originalFileChannel.size() / (double)blockLength);
063    
064                    checksumsByteChannelWriter.ensureSpace(9);
065    
066                    byteBuffer.put(PROTOCOL_VERSION);
067                    byteBuffer.putInt(blockLength);
068                    byteBuffer.putInt(blocksCount);
069    
070                    while (rollingChecksum.hasNext()) {
071                            rollingChecksum.nextBlock();
072    
073                            checksumsByteChannelWriter.ensureSpace(20);
074    
075                            byteBuffer.putInt(rollingChecksum.weakChecksum());
076                            byteBuffer.put(rollingChecksum.strongChecksum());
077                    }
078            }
079    
080            public static void delta(
081                            ReadableByteChannel modifiedReadableByteChannel,
082                            ByteChannelReader checksumsByteChannelReader,
083                            ByteChannelWriter deltaByteChannelWriter)
084                    throws IOException {
085    
086                    Differ differ = new Differ();
087    
088                    differ.delta(
089                            modifiedReadableByteChannel, checksumsByteChannelReader,
090                            deltaByteChannelWriter);
091            }
092    
093            public static void patch(
094                            FileChannel originalFileChannel,
095                            WritableByteChannel patchedWritableByteChannel,
096                            ByteChannelReader deltaByteChannelReader)
097                    throws IOException {
098    
099                    Patcher patcher = new Patcher();
100    
101                    patcher.patch(
102                            originalFileChannel, patchedWritableByteChannel,
103                            deltaByteChannelReader);
104            }
105    
106    }