diff options
author | Jean-Philippe Lesot <jplesot@google.com> | 2015-01-06 14:46:41 +0100 |
---|---|---|
committer | Jean-Philippe Lesot <jplesot@google.com> | 2015-01-08 15:22:37 +0100 |
commit | c1e2b930382ca6e663bbf0af445ccd9795b3e682 (patch) | |
tree | 7067ef9319e6b8d8ae3e8a76c53369460295dec6 | |
parent | d0de9041982de1dfe730cb4295a910016ff62c6c (diff) | |
download | toolchain_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.java | 4 | ||||
-rw-r--r-- | jack/src/com/android/jack/library/JackLibraryFactory.java | 9 | ||||
-rw-r--r-- | jack/src/com/android/jack/library/v0000/InputJackLibraryImpl.java | 7 | ||||
-rw-r--r-- | jack/src/com/android/jack/library/v0001/InputJackLibraryImpl.java | 14 | ||||
-rw-r--r-- | jack/src/com/android/jack/library/v0001/OutputJackLibraryImpl.java | 42 | ||||
-rw-r--r-- | sched/src/com/android/sched/vfs/MessageDigestInputVFS.java | 250 | ||||
-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.java | 41 |
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; + } +} |