summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Lesot <jplesot@google.com>2015-01-06 14:46:41 +0100
committerJean-Philippe Lesot <jplesot@google.com>2015-01-08 15:22:37 +0100
commitc1e2b930382ca6e663bbf0af445ccd9795b3e682 (patch)
tree7067ef9319e6b8d8ae3e8a76c53369460295dec6
parentd0de9041982de1dfe730cb4295a910016ff62c6c (diff)
downloadtoolchain_jack-c1e2b930382ca6e663bbf0af445ccd9795b3e682.tar.gz
toolchain_jack-c1e2b930382ca6e663bbf0af445ccd9795b3e682.tar.bz2
toolchain_jack-c1e2b930382ca6e663bbf0af445ccd9795b3e682.zip
Add preliminary support of digest in library.
- Add a MessageDigestOutputVFS, a VFS filter which add digest to a file - Add a MessageDigestIntputVFS, a VFS filter which read digest from file - Add a getDigest() method in InputLibrary and implementations Change-Id: I3315011b8c1fd5d455ddb71f90c267078ed3462b
-rw-r--r--jack/src/com/android/jack/library/InputLibrary.java4
-rw-r--r--jack/src/com/android/jack/library/JackLibraryFactory.java9
-rw-r--r--jack/src/com/android/jack/library/v0000/InputJackLibraryImpl.java7
-rw-r--r--jack/src/com/android/jack/library/v0001/InputJackLibraryImpl.java14
-rw-r--r--jack/src/com/android/jack/library/v0001/OutputJackLibraryImpl.java42
-rw-r--r--sched/src/com/android/sched/vfs/MessageDigestInputVFS.java250
-rw-r--r--sched/src/com/android/sched/vfs/MessageDigestOutputVFS.java (renamed from sched/src/com/android/sched/vfs/MessageDigestInputOutputVFS.java)175
-rw-r--r--sched/src/com/android/sched/vfs/MessageDigestVFS.java41
8 files changed, 417 insertions, 125 deletions
diff --git a/jack/src/com/android/jack/library/InputLibrary.java b/jack/src/com/android/jack/library/InputLibrary.java
index efd2ef62..a52a303b 100644
--- a/jack/src/com/android/jack/library/InputLibrary.java
+++ b/jack/src/com/android/jack/library/InputLibrary.java
@@ -24,6 +24,7 @@ import com.android.sched.vfs.VPath;
import java.util.Collection;
import java.util.Iterator;
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/**
@@ -51,6 +52,9 @@ public interface InputLibrary extends Library {
@Nonnull
public InputLibraryLocation getLocation();
+ @CheckForNull
+ public String getDigest();
+
@Nonnull
public void delete(@Nonnull FileType fileType, @Nonnull VPath typePath)
throws CannotDeleteFileException;
diff --git a/jack/src/com/android/jack/library/JackLibraryFactory.java b/jack/src/com/android/jack/library/JackLibraryFactory.java
index 824862c3..91d7befb 100644
--- a/jack/src/com/android/jack/library/JackLibraryFactory.java
+++ b/jack/src/com/android/jack/library/JackLibraryFactory.java
@@ -18,14 +18,12 @@ package com.android.jack.library;
import com.android.jack.library.v0001.OutputJackLibraryImpl;
import com.android.sched.util.config.HasKeyId;
-import com.android.sched.util.config.ThreadConfig;
import com.android.sched.util.config.id.BooleanPropertyId;
import com.android.sched.util.config.id.MessageDigestPropertyId;
import com.android.sched.util.log.LoggerFactory;
import com.android.sched.vfs.InputOutputVFS;
import com.android.sched.vfs.InputVFS;
import com.android.sched.vfs.InputVFile;
-import com.android.sched.vfs.MessageDigestInputOutputVFS;
import java.io.IOException;
import java.lang.reflect.Constructor;
@@ -43,11 +41,11 @@ import javax.annotation.Nonnull;
@HasKeyId
public abstract class JackLibraryFactory {
@Nonnull
- private static final BooleanPropertyId GENERATE_JACKLIB_DIGEST = BooleanPropertyId.create(
+ public static final BooleanPropertyId GENERATE_JACKLIB_DIGEST = BooleanPropertyId.create(
"jack.library.digest", "Generate message digest in Jack library").addDefaultValue(
Boolean.TRUE);
@Nonnull
- private static final MessageDigestPropertyId MESSAGE_DIGEST_ALGO = MessageDigestPropertyId
+ public static final MessageDigestPropertyId MESSAGE_DIGEST_ALGO = MessageDigestPropertyId
.create("jack.library.digest.algo", "Message digest algorithm use in Jack library")
.requiredIf(GENERATE_JACKLIB_DIGEST.getValue().isTrue()).addDefaultValue("SHA");
@@ -81,9 +79,6 @@ public abstract class JackLibraryFactory {
@Nonnull
public static OutputJackLibrary getOutputLibrary(@Nonnull InputOutputVFS vfs,
@Nonnull String emitterId, @Nonnull String emitterVersion) {
- if (ThreadConfig.get(GENERATE_JACKLIB_DIGEST).booleanValue()) {
- vfs = new MessageDigestInputOutputVFS(vfs, ThreadConfig.get(MESSAGE_DIGEST_ALGO));
- }
return new OutputJackLibraryImpl(vfs, emitterId, emitterVersion);
}
diff --git a/jack/src/com/android/jack/library/v0000/InputJackLibraryImpl.java b/jack/src/com/android/jack/library/v0000/InputJackLibraryImpl.java
index b8240a4c..4db3adc1 100644
--- a/jack/src/com/android/jack/library/v0000/InputJackLibraryImpl.java
+++ b/jack/src/com/android/jack/library/v0000/InputJackLibraryImpl.java
@@ -43,6 +43,7 @@ import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
@@ -193,4 +194,10 @@ public class InputJackLibraryImpl extends InputJackLibrary {
public String getPath() {
return vfs.getPath();
}
+
+ @Override
+ @CheckForNull
+ public String getDigest() {
+ return null;
+ }
}
diff --git a/jack/src/com/android/jack/library/v0001/InputJackLibraryImpl.java b/jack/src/com/android/jack/library/v0001/InputJackLibraryImpl.java
index e0402b94..d648c176 100644
--- a/jack/src/com/android/jack/library/v0001/InputJackLibraryImpl.java
+++ b/jack/src/com/android/jack/library/v0001/InputJackLibraryImpl.java
@@ -33,6 +33,7 @@ import com.android.sched.util.log.LoggerFactory;
import com.android.sched.vfs.InputVDir;
import com.android.sched.vfs.InputVFS;
import com.android.sched.vfs.InputVFile;
+import com.android.sched.vfs.MessageDigestInputVFS;
import com.android.sched.vfs.VPath;
import java.io.IOException;
@@ -43,6 +44,7 @@ import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
@@ -54,7 +56,7 @@ public class InputJackLibraryImpl extends InputJackLibrary {
private static Logger logger = LoggerFactory.getLogger();
@Nonnull
- private final InputVFS vfs;
+ private final MessageDigestInputVFS vfs;
@Nonnegative
private final int minorVersion;
@@ -84,11 +86,11 @@ public class InputJackLibraryImpl extends InputJackLibrary {
}
};
- public InputJackLibraryImpl(@Nonnull InputVFS libraryVDir,
+ public InputJackLibraryImpl(@Nonnull InputVFS vfs,
@Nonnull Properties libraryProperties) throws LibraryVersionException,
LibraryFormatException {
super(libraryProperties);
- this.vfs = libraryVDir;
+ this.vfs = new MessageDigestInputVFS(vfs);
try {
minorVersion = Integer.parseInt(getProperty(KEY_LIB_MINOR_VERSION));
@@ -201,4 +203,10 @@ public class InputJackLibraryImpl extends InputJackLibrary {
public String getPath() {
return vfs.getPath();
}
+
+ @Override
+ @CheckForNull
+ public String getDigest() {
+ return vfs.getDigest();
+ }
}
diff --git a/jack/src/com/android/jack/library/v0001/OutputJackLibraryImpl.java b/jack/src/com/android/jack/library/v0001/OutputJackLibraryImpl.java
index e9fd999e..bf340738 100644
--- a/jack/src/com/android/jack/library/v0001/OutputJackLibraryImpl.java
+++ b/jack/src/com/android/jack/library/v0001/OutputJackLibraryImpl.java
@@ -18,16 +18,21 @@ package com.android.jack.library.v0001;
import com.android.jack.library.FileType;
import com.android.jack.library.FileTypeDoesNotExistException;
+import com.android.jack.library.JackLibraryFactory;
import com.android.jack.library.LibraryIOException;
import com.android.jack.library.OutputJackLibrary;
import com.android.jack.library.OutputLibrary;
import com.android.jack.library.OutputLibraryLocation;
+import com.android.sched.util.config.ThreadConfig;
import com.android.sched.util.file.CannotCreateFileException;
import com.android.sched.util.file.CannotDeleteFileException;
import com.android.sched.util.file.NoSuchFileException;
import com.android.sched.util.file.NotFileOrDirectoryException;
import com.android.sched.vfs.InputOutputVFS;
+import com.android.sched.vfs.InputVFS;
import com.android.sched.vfs.InputVFile;
+import com.android.sched.vfs.MessageDigestOutputVFS;
+import com.android.sched.vfs.OutputVFS;
import com.android.sched.vfs.OutputVFile;
import com.android.sched.vfs.SequentialOutputVFS;
import com.android.sched.vfs.VPath;
@@ -49,14 +54,16 @@ public class OutputJackLibraryImpl extends OutputJackLibrary {
private boolean closed = false;
@Nonnull
- private final InputOutputVFS vfs;
+ private final InputVFS iVfs;
+ @Nonnull
+ private final OutputVFS oVfs;
@Nonnull
private final OutputLibraryLocation location = new OutputLibraryLocation() {
@Override
@Nonnull
public String getDescription() {
- return vfs.getLocation().getDescription();
+ return oVfs.getLocation().getDescription();
}
@Override
@@ -77,10 +84,19 @@ public class OutputJackLibraryImpl extends OutputJackLibrary {
}
};
- public OutputJackLibraryImpl(@Nonnull InputOutputVFS outputVDir, @Nonnull String emitterId,
+ public OutputJackLibraryImpl(@Nonnull InputOutputVFS vfs, @Nonnull String emitterId,
@Nonnull String emitterVersion) {
super(new Properties());
- this.vfs = outputVDir;
+
+ this.iVfs = vfs;
+
+ if (ThreadConfig.get(JackLibraryFactory.GENERATE_JACKLIB_DIGEST).booleanValue()) {
+ this.oVfs =
+ new MessageDigestOutputVFS(vfs, ThreadConfig.get(JackLibraryFactory.MESSAGE_DIGEST_ALGO));
+ } else {
+ this.oVfs = vfs;
+ }
+
putProperty(KEY_LIB_EMITTER, emitterId);
putProperty(KEY_LIB_EMITTER_VERSION, emitterVersion);
putProperty(KEY_LIB_MAJOR_VERSION, String.valueOf(getMajorVersion()));
@@ -94,12 +110,13 @@ public class OutputJackLibraryImpl extends OutputJackLibrary {
assert !isClosed();
putProperty(fileType.buildPropertyName(null /*suffix*/), String.valueOf(true));
addFileType(fileType);
- return vfs.getRootInputOutputVDir().createOutputVFile(fileType.buildFileVPath(typePath));
+ return oVfs.getRootOutputVDir().createOutputVFile(fileType.buildFileVPath(typePath));
}
@Override
public boolean needsSequentialWriting() {
- return vfs instanceof SequentialOutputVFS;
+ // XXX Rework
+ return iVfs instanceof SequentialOutputVFS;
}
@Override
@@ -114,7 +131,7 @@ public class OutputJackLibraryImpl extends OutputJackLibrary {
OutputStream os = null;
try {
OutputVFile libraryPropertiesOut =
- vfs.getRootInputOutputVDir().createOutputVFile(LIBRARY_PROPERTIES_VPATH);
+ oVfs.getRootOutputVDir().createOutputVFile(LIBRARY_PROPERTIES_VPATH);
os = libraryPropertiesOut.openWrite();
libraryProperties.store(os, "Library properties");
} catch (CannotCreateFileException e) {
@@ -132,7 +149,8 @@ public class OutputJackLibraryImpl extends OutputJackLibrary {
}
try {
- vfs.close();
+ oVfs.close();
+ iVfs.close();
} catch (IOException e) {
throw new LibraryIOException(getLocation(), e);
}
@@ -154,7 +172,7 @@ public class OutputJackLibraryImpl extends OutputJackLibrary {
@Nonnull
public Iterator<InputVFile> iterator(@Nonnull FileType fileType) {
List<InputVFile> inputVFiles = new ArrayList<InputVFile>();
- fillFiles(vfs.getRootInputOutputVDir(), fileType, inputVFiles);
+ fillFiles(iVfs.getRootInputVDir(), fileType, inputVFiles);
return inputVFiles.listIterator();
}
@@ -163,7 +181,7 @@ public class OutputJackLibraryImpl extends OutputJackLibrary {
public InputVFile getFile(@Nonnull FileType fileType, @Nonnull VPath typePath)
throws FileTypeDoesNotExistException {
try {
- return vfs.getRootInputOutputVDir().getInputVFile(fileType.buildFileVPath(typePath));
+ return iVfs.getRootInputVDir().getInputVFile(fileType.buildFileVPath(typePath));
} catch (NotFileOrDirectoryException e) {
throw new FileTypeDoesNotExistException(getLocation(), typePath, fileType);
} catch (NoSuchFileException e) {
@@ -176,13 +194,13 @@ public class OutputJackLibraryImpl extends OutputJackLibrary {
public void delete(@Nonnull FileType fileType, @Nonnull VPath typePath)
throws CannotDeleteFileException {
assert !isClosed();
- vfs.getRootInputOutputVDir().delete(fileType.buildFileVPath(typePath));
+ iVfs.getRootInputVDir().delete(fileType.buildFileVPath(typePath));
}
@Override
@Nonnull
public String getPath() {
- return vfs.getPath();
+ return oVfs.getPath();
}
private synchronized boolean isClosed() {
diff --git a/sched/src/com/android/sched/vfs/MessageDigestInputVFS.java b/sched/src/com/android/sched/vfs/MessageDigestInputVFS.java
new file mode 100644
index 00000000..c844629b
--- /dev/null
+++ b/sched/src/com/android/sched/vfs/MessageDigestInputVFS.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2014 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.sched.vfs;
+
+import com.android.sched.util.file.CannotDeleteFileException;
+import com.android.sched.util.file.NoSuchFileException;
+import com.android.sched.util.file.NotFileOrDirectoryException;
+import com.android.sched.util.location.Location;
+import com.android.sched.util.log.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+/**
+ * An {@link InputVFS} which read a file with message digest of each file in the VFS.
+ */
+public class MessageDigestInputVFS extends MessageDigestVFS implements InputVFS {
+ @Nonnull
+ private static final Logger logger = LoggerFactory.getLogger();
+
+ @Nonnull
+ protected InputVFS vfs;
+ @Nonnull
+ private final MessageDigestInputVDir root;
+ @Nonnull
+ private final Map<VPath, String> digests = new HashMap<VPath, String>();
+ @CheckForNull
+ private String algorithm = null;
+ @CheckForNull
+ private String digest = null;
+
+ /**
+ * An {@link InputVFile} which have a message digest.
+ */
+ public static class MessageDigestInputVFile implements InputVFile {
+ @Nonnull
+ private final InputVFile file;
+ @CheckForNull
+ private final String digest;
+
+ public MessageDigestInputVFile(@Nonnull InputVFile file, @CheckForNull String digest) {
+ this.file = file;
+ this.digest = digest;
+ }
+
+ @Override
+ public boolean isVDir() {
+ return false;
+ }
+
+ @Override
+ @Nonnull
+ public String getName() {
+ return file.getName();
+ }
+
+ @Override
+ @Nonnull
+ public Location getLocation() {
+ return file.getLocation();
+ }
+
+ @Override
+ @Nonnull
+ public InputStream openRead() throws IOException {
+ return file.openRead();
+ }
+
+ @CheckForNull
+ public String getDigest() {
+ return digest;
+ }
+ }
+
+ /**
+ * An {@link InputVDir} which return {@link MessageDigestInputVFile}.
+ */
+ public class MessageDigestInputVDir implements InputVDir {
+ @Nonnull
+ private final InputVDir dir;
+
+ private MessageDigestInputVDir (@Nonnull InputVDir dir) {
+ this.dir = dir;
+ }
+
+ @Override
+ public boolean isVDir() {
+ return true;
+ }
+
+ @Override
+ @Nonnull
+ public String getName() {
+ return dir.getName();
+ }
+
+ @Override
+ @Nonnull
+ public Location getLocation() {
+ return dir.getLocation();
+ }
+
+ @Override
+ @Nonnull
+ public Collection<? extends InputVElement> list() {
+ return dir.list();
+ }
+
+ @Override
+ @Nonnull
+ public MessageDigestInputVDir getInputVDir(@Nonnull VPath path)
+ throws NotFileOrDirectoryException, NoSuchFileException {
+ return new MessageDigestInputVDir(dir.getInputVDir(path));
+ }
+
+ @Override
+ @Nonnull
+ public MessageDigestInputVFile getInputVFile(@Nonnull VPath path)
+ throws NotFileOrDirectoryException, NoSuchFileException {
+ // XXX Add relative VPath support
+ return new MessageDigestInputVFile(dir.getInputVFile(path), digests.get(path));
+ }
+
+ @Override
+ @Nonnull
+ public void delete(@Nonnull VPath path) throws CannotDeleteFileException {
+ dir.delete(path);
+ }
+ }
+
+ public MessageDigestInputVFS(@Nonnull InputVFS vfs) {
+ this.root = new MessageDigestInputVDir(vfs.getRootInputVDir());
+ this.vfs = vfs;
+
+ // Reading digest directory is best effort
+ // If there is one error, let's skip that step
+ BufferedReader in = null;
+ InputVFile file = null;
+ try {
+ try {
+ file = root.getInputVFile(new VPath(DIGEST_DIRECTORY_NAME, '/'));
+ } catch (NotFileOrDirectoryException e) {
+ logger.log(Level.WARNING, "Cannot open '" + DIGEST_DIRECTORY_NAME + "' file in {0}", vfs
+ .getLocation().getDescription());
+ logger.log(Level.WARNING, "Stacktrace", e);
+ return;
+ } catch (NoSuchFileException e) {
+ logger.log(Level.WARNING, "Cannot open '" + DIGEST_DIRECTORY_NAME + "' file in {0}", vfs
+ .getLocation().getDescription());
+ logger.log(Level.WARNING, "Stacktrace", e);
+ return;
+ }
+
+ try {
+ in = new BufferedReader(new InputStreamReader(file.openRead()));
+ } catch (IOException e) {
+ logger.log(Level.WARNING, "Cannot open {0}", file.getLocation().getDescription());
+ logger.log(Level.WARNING, "Stacktrace", e);
+ return;
+ }
+
+ try {
+ algorithm = in.readLine();
+
+ String line;
+ while ((line = in.readLine()) != null) {
+ int index = line.indexOf(':');
+ if (index < 1) {
+ logger.log(Level.WARNING, "Bad format in {0}", file.getLocation().getDescription());
+ continue;
+ }
+
+ digests.put(new VPath(line.substring(index + 1), '/'), line.substring(0, index));
+ }
+ } catch (IOException e) {
+ logger.log(Level.WARNING, "Error reading {0}", file.getLocation().getDescription());
+ return;
+ }
+
+ digest = digests.get(new VPath(MessageDigestOutputVFS.DIGEST_DIRECTORY_NAME, '/'));
+ } finally {
+ if (in != null) {
+ assert file != null;
+
+ try {
+ in.close();
+ } catch (IOException e) {
+ logger.log(Level.WARNING, "Cannot close {0}", file.getLocation().getDescription());
+ }
+ }
+ }
+ }
+
+ @Override
+ @Nonnull
+ public Location getLocation() {
+ return vfs.getLocation();
+ }
+
+ @Override
+ public synchronized void close() throws IOException {
+ vfs.close();
+ }
+
+ @Override
+ @Nonnull
+ public MessageDigestInputVDir getRootInputVDir() {
+ return root;
+ }
+
+ @Override
+ @Nonnull
+ public String getPath() {
+ return vfs.getPath();
+ }
+
+ @CheckForNull
+ public String getDigestAlgorithm() {
+ return algorithm;
+ }
+
+ @CheckForNull
+ public String getDigest() {
+ return digest;
+ }
+}
diff --git a/sched/src/com/android/sched/vfs/MessageDigestInputOutputVFS.java b/sched/src/com/android/sched/vfs/MessageDigestOutputVFS.java
index eb64b963..7d5aa3d2 100644
--- a/sched/src/com/android/sched/vfs/MessageDigestInputOutputVFS.java
+++ b/sched/src/com/android/sched/vfs/MessageDigestOutputVFS.java
@@ -16,11 +16,9 @@
package com.android.sched.vfs;
+import com.android.sched.util.collect.Lists;
import com.android.sched.util.config.MessageDigestFactory;
import com.android.sched.util.file.CannotCreateFileException;
-import com.android.sched.util.file.CannotDeleteFileException;
-import com.android.sched.util.file.NoSuchFileException;
-import com.android.sched.util.file.NotFileOrDirectoryException;
import com.android.sched.util.location.Location;
import java.io.IOException;
@@ -28,31 +26,33 @@ import java.io.OutputStream;
import java.io.PrintStream;
import java.security.DigestOutputStream;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/**
- * An {@link InputOutputVFS} which generated a file with message digest of each file in a VFS.
+ * An {@link OutputVFS} which generates a file with message digest of each file in a VFS.
*/
-public class MessageDigestInputOutputVFS implements InputOutputVFS {
+public class MessageDigestOutputVFS extends MessageDigestVFS implements OutputVFS {
private boolean closed = false;
@Nonnull
protected OutputVFS vfs;
@Nonnull
- private final MessageDigestInputOutputVDir root;
+ private final MessageDigestOutputVDir root;
@Nonnull
private final MessageDigestFactory mdFactory;
+ @Nonnull
+ private final List<MessageDigestOutputVFile> files = new ArrayList<MessageDigestOutputVFile>();
- private class MessageDigestOutputVFile implements OutputVFile {
+ private class MessageDigestOutputVFile implements OutputVFile,
+ Comparable<MessageDigestOutputVFile> {
@Nonnull
private final OutputVFile file;
@Nonnull
private final VPath path;
@CheckForNull
- private byte[] digest;
+ private String digest = null;
protected MessageDigestOutputVFile(@Nonnull OutputVFile file, @Nonnull VPath path) {
this.file = file;
@@ -82,17 +82,18 @@ public class MessageDigestInputOutputVFS implements InputOutputVFS {
assert !isClosed();
return new DigestOutputStream(file.openWrite(),
- MessageDigestInputOutputVFS.this.mdFactory.create()) {
+ MessageDigestOutputVFS.this.mdFactory.create()) {
@Override
public void close() throws IOException {
super.close();
- MessageDigestOutputVFile.this.digest = getMessageDigest().digest();
+ MessageDigestOutputVFile.this.digest =
+ new String(encode(getMessageDigest().digest()));
}
};
}
@CheckForNull
- public byte[] getDigest() {
+ public String getDigest() {
return digest;
}
@@ -100,15 +101,33 @@ public class MessageDigestInputOutputVFS implements InputOutputVFS {
public VPath getVPath() {
return path;
}
+
+ @Override
+ public int compareTo(MessageDigestOutputVFile other) {
+ return path.getPathAsString('/').compareTo(other.getVPath().getPathAsString('/'));
+ }
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (!(obj instanceof MessageDigestOutputVFile)) {
+ return false;
+ }
+
+ return path.getPathAsString('/').equals(
+ ((MessageDigestOutputVFile) obj).getVPath().getPathAsString('/'));
+ }
+
+ @Override
+ public final int hashCode() {
+ return path.getPathAsString('.').hashCode();
+ }
}
- private class MessageDigestInputOutputVDir implements InputOutputVDir {
- @Nonnull
- private final InputOutputVDir dir;
+ private class MessageDigestOutputVDir implements OutputVDir {
@Nonnull
- private final List<MessageDigestOutputVFile> files = new ArrayList<MessageDigestOutputVFile>();
+ private final OutputVDir dir;
- protected MessageDigestInputOutputVDir (@Nonnull InputOutputVDir dir) {
+ protected MessageDigestOutputVDir (@Nonnull OutputVDir dir) {
this.dir = dir;
}
@@ -131,72 +150,21 @@ public class MessageDigestInputOutputVFS implements InputOutputVFS {
@Override
@Nonnull
- public synchronized OutputVFile createOutputVFile(@Nonnull VPath path)
+ public synchronized MessageDigestOutputVFile createOutputVFile(@Nonnull VPath path)
throws CannotCreateFileException {
assert !isClosed();
MessageDigestOutputVFile file =
new MessageDigestOutputVFile(dir.createOutputVFile(path), path);
- files.add(file);
+ addFile(file);
return file;
}
-
- private synchronized void close() throws CannotCreateFileException, IOException {
- OutputStream os = dir.createOutputVFile(new VPath("jack.sha1", '/')).openWrite();
- PrintStream printer = new PrintStream(os);
-
- for (MessageDigestOutputVFile file : files) {
- byte[] digest = file.getDigest();
- if (digest != null) {
- printer.print(file.getVPath().getPathAsString('/'));
- printer.print(':');
- printer.print(encode(digest));
- printer.println();
- }
- }
-
- printer.close();
- }
-
- @Override
- @Nonnull
- public Collection<? extends InputVElement> list() {
- assert !isClosed();
-
- return dir.list();
- }
-
- @Override
- @Nonnull
- public InputVDir getInputVDir(@Nonnull VPath path) throws NotFileOrDirectoryException,
- NoSuchFileException {
- assert !isClosed();
-
- return dir.getInputVDir(path);
- }
-
- @Override
- @Nonnull
- public InputVFile getInputVFile(@Nonnull VPath path) throws NotFileOrDirectoryException,
- NoSuchFileException {
- assert !isClosed();
-
- return dir.getInputVFile(path);
- }
-
- @Override
- @Nonnull
- public void delete(@Nonnull VPath path) throws CannotDeleteFileException {
- assert !isClosed();
-
- dir.delete(path);
- }
}
- public MessageDigestInputOutputVFS(@Nonnull InputOutputVFS vfs,
+ public MessageDigestOutputVFS(@Nonnull OutputVFS vfs,
@Nonnull MessageDigestFactory mdFactory) {
- this.root = new MessageDigestInputOutputVDir(vfs.getRootInputOutputVDir());
+ this.root = new MessageDigestOutputVDir(vfs.getRootOutputVDir());
this.vfs = vfs;
this.mdFactory = mdFactory;
}
@@ -210,35 +178,46 @@ public class MessageDigestInputOutputVFS implements InputOutputVFS {
@Override
public synchronized void close() throws IOException {
if (!closed) {
- root.close();
+ List<MessageDigestOutputVFile> sortedFiles = Lists.<MessageDigestOutputVFile> sort(files);
+
+ DigestOutputStream os =
+ new DigestOutputStream(root.createOutputVFile(new VPath(DIGEST_DIRECTORY_NAME, '/'))
+ .openWrite(), MessageDigestOutputVFS.this.mdFactory.create());
+ PrintStream printer = new PrintStream(os);
+
+ printer.println(mdFactory.getService().getAlgorithm());
+
+ for (MessageDigestOutputVFile file : sortedFiles) {
+ String digest = file.getDigest();
+ if (digest != null) {
+ printer.print(digest);
+ printer.print(':');
+ printer.print(file.getVPath().getPathAsString('/'));
+ printer.println();
+ }
+ }
+
+ printer.flush();
+
+ String digest = new String(encode(os.getMessageDigest().digest()));
+ printer.print(digest);
+ printer.print(':' + DIGEST_DIRECTORY_NAME);
+ printer.println();
+
+ printer.close();
+
vfs.close();
closed = true;
}
}
- synchronized boolean isClosed() {
+ private synchronized boolean isClosed() {
return closed;
}
@Override
@Nonnull
- public OutputVDir getRootOutputVDir() {
- assert !isClosed();
-
- return root;
- }
-
- @Override
- @Nonnull
- public InputVDir getRootInputVDir() {
- assert !isClosed();
-
- return root;
- }
-
- @Override
- @Nonnull
- public InputOutputVDir getRootInputOutputVDir() {
+ public MessageDigestOutputVDir getRootOutputVDir() {
assert !isClosed();
return root;
@@ -250,17 +229,7 @@ public class MessageDigestInputOutputVFS implements InputOutputVFS {
return vfs.getPath();
}
- @Nonnull
- private static final byte[] code = "0123456789ABCDEF".getBytes();
- @Nonnull
- private static char[] encode(@Nonnull byte[] bytes) {
- char[] array = new char[bytes.length * 2];
-
- for (int idx = 0; idx < bytes.length; idx++) {
- array[(idx << 1) ] = (char) code[(bytes[idx] & 0xF0) >> 4];
- array[(idx << 1) + 1] = (char) code[(bytes[idx] & 0x0F) ];
- }
-
- return array;
+ private synchronized void addFile(@Nonnull MessageDigestOutputVFile file) {
+ files.add(file);
}
}
diff --git a/sched/src/com/android/sched/vfs/MessageDigestVFS.java b/sched/src/com/android/sched/vfs/MessageDigestVFS.java
new file mode 100644
index 00000000..eb8458fe
--- /dev/null
+++ b/sched/src/com/android/sched/vfs/MessageDigestVFS.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014 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.sched.vfs;
+
+import javax.annotation.Nonnull;
+
+
+/**
+ * Abstract base class for message digest VFS.
+ */
+abstract class MessageDigestVFS {
+ static final String DIGEST_DIRECTORY_NAME = ".digest";
+
+ @Nonnull
+ private static final byte[] code = "0123456789ABCDEF".getBytes();
+ @Nonnull
+ static char[] encode(@Nonnull byte[] bytes) {
+ char[] array = new char[bytes.length * 2];
+
+ for (int idx = 0; idx < bytes.length; idx++) {
+ array[(idx << 1) ] = (char) code[(bytes[idx] & 0xF0) >> 4];
+ array[(idx << 1) + 1] = (char) code[(bytes[idx] & 0x0F) ];
+ }
+
+ return array;
+ }
+}