• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.jf.dexlib2.writer.io;
2 
3 import com.google.common.io.ByteStreams;
4 
5 import javax.annotation.Nonnull;
6 import javax.annotation.Nullable;
7 import java.io.*;
8 
9 /**
10  * A deferred output stream that uses a file as its backing store, with a in-memory intermediate buffer.
11  */
12 public class FileDeferredOutputStream extends DeferredOutputStream {
13     private static final int DEFAULT_BUFFER_SIZE = 4 * 1024;
14 
15     @Nonnull private final File backingFile;
16     @Nonnull private final NakedBufferedOutputStream output;
17     private int writtenBytes;
18 
FileDeferredOutputStream(@onnull File backingFile)19     public FileDeferredOutputStream(@Nonnull File backingFile) throws FileNotFoundException {
20         this(backingFile, DEFAULT_BUFFER_SIZE);
21     }
22 
FileDeferredOutputStream(@onnull File backingFile, int bufferSize)23     public FileDeferredOutputStream(@Nonnull File backingFile, int bufferSize) throws FileNotFoundException {
24         this.backingFile = backingFile;
25         output = new NakedBufferedOutputStream(new FileOutputStream(backingFile), bufferSize);
26     }
27 
writeTo(@onnull OutputStream dest)28     @Override public void writeTo(@Nonnull OutputStream dest) throws IOException {
29         byte[] outBuf = output.getBuffer();
30         int count = output.getCount();
31         output.resetBuffer();
32         output.close();
33 
34         // did we actually write something out to disk?
35         if (count != writtenBytes) {
36             InputStream fis = new FileInputStream(backingFile);
37             ByteStreams.copy(fis, dest);
38             backingFile.delete();
39         }
40 
41         dest.write(outBuf, 0, count);
42     }
43 
write(int i)44     @Override public void write(int i) throws IOException {
45         output.write(i);
46         writtenBytes++;
47     }
48 
write(byte[] bytes)49     @Override public void write(byte[] bytes) throws IOException {
50         output.write(bytes);
51         writtenBytes += bytes.length;
52     }
53 
write(byte[] bytes, int off, int len)54     @Override public void write(byte[] bytes, int off, int len) throws IOException {
55         output.write(bytes, off, len);
56         writtenBytes += len;
57     }
58 
flush()59     @Override public void flush() throws IOException {
60         output.flush();
61     }
62 
close()63     @Override public void close() throws IOException {
64         output.close();
65     }
66 
67     private static class NakedBufferedOutputStream extends BufferedOutputStream {
NakedBufferedOutputStream(OutputStream outputStream)68         public NakedBufferedOutputStream(OutputStream outputStream) {
69             super(outputStream);
70         }
71 
NakedBufferedOutputStream(OutputStream outputStream, int i)72         public NakedBufferedOutputStream(OutputStream outputStream, int i) {
73             super(outputStream, i);
74         }
75 
getCount()76         public int getCount() {
77             return count;
78         }
79 
resetBuffer()80         public void resetBuffer() {
81             count = 0;
82         }
83 
getBuffer()84         public byte[] getBuffer() {
85             return buf;
86         }
87     }
88 
89     @Nonnull
getFactory(@ullable File containingDirectory)90     public static DeferredOutputStreamFactory getFactory(@Nullable File containingDirectory) {
91         return getFactory(containingDirectory, DEFAULT_BUFFER_SIZE);
92     }
93 
94     @Nonnull
getFactory(@ullable final File containingDirectory, final int bufferSize)95     public static DeferredOutputStreamFactory getFactory(@Nullable final File containingDirectory,
96                                                          final int bufferSize) {
97         return new DeferredOutputStreamFactory() {
98             @Override public DeferredOutputStream makeDeferredOutputStream() throws IOException {
99                 File tempFile = File.createTempFile("dexlibtmp", null, containingDirectory);
100                 return new FileDeferredOutputStream(tempFile, bufferSize);
101             }
102         };
103     }
104 }
105