Java tutorial
/* * Copyright (C) 2012 The Android Open Source Project * * 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 com.android.builder.internal.incremental; import com.google.common.hash.HashCode; import com.google.common.hash.Hashing; import com.google.common.io.ByteStreams; import com.google.common.io.Files; import java.io.File; /** * A {@link File} and its associated data needed to figure out if a file changed or not. */ class FileEntity { private static final byte[] sBuffer = new byte[4096]; private final File mFile; private final long mLastModified; private long mLength; private String mSha1; /** * Exception to indicate a failure to check a jar file's content. */ private static final class Sha1Exception extends Exception { private static final long serialVersionUID = 1L; private final File file; public Sha1Exception(File jarFile, Throwable cause) { super(cause); file = jarFile; } public File getJarFile() { return file; } } /** * Creates an entity from cached data. * * @param file the file * @param lastModified when it was last modified * @param length its length * @param sha1 its sha1 */ FileEntity(File file, long lastModified, long length, String sha1) { mFile = file; mLastModified = lastModified; mLength = length; mSha1 = sha1; } /** * Creates an entity from a {@link File}. * * The sha1 is not computed yet, it'll be done on demand when {@link #getSha1()} is called. * * @param file the file. */ FileEntity(File file) { mFile = file; mLastModified = file.lastModified(); mLength = file.length(); } /** * Returns the file's last modified info. * @return the file's last modified info. */ long getLastModified() { return mLastModified; } /** * Return the file length. * @return the file length. */ long getLength() { return mLength; } /** * Returns the file this entity represents. * @return the file. */ File getFile() { return mFile; } /** * Returns the file's sha1, computing it if necessary. * * @return the fha1 or null if it couldn't be computed. */ String getSha1() { try { return computeAndReturnSha1(); } catch (Sha1Exception e) { return null; } } /** * Checks whether the {@link File#lastModified()} matches the cached value. If not, length * is updated and the sha1 is reset (but not recomputed, this is done on demand). * * @return return whether the file was changed. */ private boolean checkValidity() { if (mLastModified != mFile.lastModified()) { mLength = mFile.length(); mSha1 = null; return true; } return false; } /** * Returns whether the two entity are different files. * * This will compute the files' sha1 if they are not yet computed. * * @param fileEntity the file to compare to. * @return true if the files are the same, false otherwise. */ public boolean isDifferentThan(FileEntity fileEntity) { assert fileEntity.mFile.equals(mFile); // same date, same files. if (mLastModified == fileEntity.mLastModified) { return false; } try { // different date doesn't necessarily mean different file. // start with size, less computing intensive than sha1. return mLength != fileEntity.mLength || !computeAndReturnSha1().equals(fileEntity.computeAndReturnSha1()); } catch (Sha1Exception e) { // if we can't compute the sha1, we consider the files different. return true; } } /** * Returns the file's sha1, computing it if necessary. * * @return the sha1 * @throws Sha1Exception */ private String computeAndReturnSha1() throws Sha1Exception { if (mSha1 == null) { mSha1 = getSha1(mFile); } return mSha1; } /** * Computes the sha1 of a file and returns it. * * @param f the file to compute the sha1 for. * @return the sha1 value * @throws Sha1Exception if the sha1 value cannot be computed. */ static String getSha1(File f) throws Sha1Exception { synchronized (sBuffer) { try { HashCode value = ByteStreams.hash(Files.newInputStreamSupplier(f), Hashing.sha1()); return value.toString(); } catch (Exception e) { throw new Sha1Exception(f, e); } } } @Override public String toString() { return "FileEntity{" + "mFile=" + mFile + ", mLastModified=" + mLastModified + ", mLength=" + mLength + ", mSha1='" + mSha1 + '\'' + '}'; } }