199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverpackage org.jf.dexlib2.writer.io; 299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverimport com.google.common.io.ByteStreams; 499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverimport javax.annotation.Nonnull; 699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverimport javax.annotation.Nullable; 799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverimport java.io.*; 899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver/** 1099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver * A deferred output stream that uses a file as its backing store, with a in-memory intermediate buffer. 1199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver */ 1299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverpublic class FileDeferredOutputStream extends DeferredOutputStream { 1399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver private static final int DEFAULT_BUFFER_SIZE = 4 * 1024; 1499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 1599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Nonnull private final File backingFile; 1699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Nonnull private final NakedBufferedOutputStream output; 1799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver private int writtenBytes; 1899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 1999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public FileDeferredOutputStream(@Nonnull File backingFile) throws FileNotFoundException { 2099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver this(backingFile, DEFAULT_BUFFER_SIZE); 2199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 2299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 2399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public FileDeferredOutputStream(@Nonnull File backingFile, int bufferSize) throws FileNotFoundException { 2499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver this.backingFile = backingFile; 2599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver output = new NakedBufferedOutputStream(new FileOutputStream(backingFile), bufferSize); 2699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 2799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 2899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public void writeTo(@Nonnull OutputStream dest) throws IOException { 2999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver byte[] outBuf = output.getBuffer(); 3099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver int count = output.getCount(); 3199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver output.resetBuffer(); 3299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver output.close(); 3399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 3499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver // did we actually write something out to disk? 3599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver if (count != writtenBytes) { 3699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver InputStream fis = new FileInputStream(backingFile); 3799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver ByteStreams.copy(fis, dest); 3899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver backingFile.delete(); 3999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 4099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 4199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver dest.write(outBuf, 0, count); 4299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 4399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 4499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public void write(int i) throws IOException { 4599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver output.write(i); 4699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver writtenBytes++; 4799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 4899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 4999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public void write(byte[] bytes) throws IOException { 5099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver output.write(bytes); 5199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver writtenBytes += bytes.length; 5299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 5399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 5499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public void write(byte[] bytes, int off, int len) throws IOException { 5599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver output.write(bytes, off, len); 5699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver writtenBytes += len; 5799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 5899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 5999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public void flush() throws IOException { 6099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver output.flush(); 6199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 6299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 6399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public void close() throws IOException { 6499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver output.close(); 6599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 6699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 6799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver private static class NakedBufferedOutputStream extends BufferedOutputStream { 6899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public NakedBufferedOutputStream(OutputStream outputStream) { 6999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver super(outputStream); 7099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 7199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 7299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public NakedBufferedOutputStream(OutputStream outputStream, int i) { 7399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver super(outputStream, i); 7499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 7599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 7699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public int getCount() { 7799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver return count; 7899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 7999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 8099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public void resetBuffer() { 8199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver count = 0; 8299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 8399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 8499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public byte[] getBuffer() { 8599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver return buf; 8699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 8799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 8899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 8999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Nonnull 9099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public static DeferredOutputStreamFactory getFactory(@Nullable File containingDirectory) { 9199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver return getFactory(containingDirectory, DEFAULT_BUFFER_SIZE); 9299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 9399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 9499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Nonnull 9599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public static DeferredOutputStreamFactory getFactory(@Nullable final File containingDirectory, 9699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver final int bufferSize) { 9799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver return new DeferredOutputStreamFactory() { 9899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public DeferredOutputStream makeDeferredOutputStream() throws IOException { 9999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver File tempFile = File.createTempFile("dexlibtmp", null, containingDirectory); 10099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver return new FileDeferredOutputStream(tempFile, bufferSize); 10199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 10299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver }; 10399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 10499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver} 105