/** * Copyright 2009 Google Inc. * * Licensed 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. * */ package org.waveprotocol.wave.model.version; import com.google.common.annotations.VisibleForTesting; import org.waveprotocol.wave.model.id.IdURIEncoderDecoder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * Factory for creating arbitrary hashed versions. */ public class HashedVersionFactoryImpl extends HashedVersionZeroFactoryImpl { /** The first N bits of a SHA-256 hash are stored in the hash must be <= 256 */ private static final int HASH_SIZE_BITS = 160; @VisibleForTesting // Allow override for unit testing. static int hashSizeBits = HASH_SIZE_BITS; public HashedVersionFactoryImpl(IdURIEncoderDecoder uriCodec) { super(uriCodec); } private static byte[] calculateHash(byte[] historyHash, byte[] appliedDeltaBytes) { byte[] joined = new byte[appliedDeltaBytes.length + historyHash.length]; byte[] result = new byte[hashSizeBits / 8]; System.arraycopy(historyHash, 0, joined, 0, historyHash.length); System.arraycopy(appliedDeltaBytes, 0, joined, historyHash.length, appliedDeltaBytes.length); try { historyHash = MessageDigest.getInstance("SHA-256").digest(joined); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } System.arraycopy(historyHash, 0, result, 0, result.length); return result; } @Override public HashedVersion create(byte[] appliedDeltaBytes, HashedVersion hashedVersionAppliedAt, int operationsApplied) { return HashedVersion.of(hashedVersionAppliedAt.getVersion() + operationsApplied, calculateHash(hashedVersionAppliedAt.getHistoryHash(), appliedDeltaBytes)); } }