View Javadoc
1   package de.japrost.jabudget.serialization;
2   
3   import java.io.File;
4   import java.io.FileDescriptor;
5   import java.io.FileInputStream;
6   import java.io.FileNotFoundException;
7   import java.io.IOException;
8   import java.io.InputStream;
9   import java.io.OutputStream;
10  import java.nio.channels.FileChannel;
11  
12  /**
13   * An {@link InputStream} that uses a {@link FileInputStream} internally, which is created when the first acces is done.
14   * On {@link InputStream#close()} the internal {@link FileInputStream} will be closed and unset that next reading all
15   * will get a new stream.
16   */
17  // TODO move to a io project
18  public class LazyFileInputStream extends InputStream {
19  
20  	private final File file;
21  	private FileInputStream delegate;
22  
23  	/**
24  	 * Create a {@link LazyFileInputStream} to be based on the given {@link File}.
25  	 *
26  	 * @param file the file to use in the delegate.
27  	 */
28  	public LazyFileInputStream(final File file) {
29  		// TODO require non null
30  		this.file = file;
31  	}
32  
33  	/**
34  	 * {@inheritDoc}
35  	 * <p>
36  	 * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
37  	 * {@link FileInputStream#read()}.
38  	 */
39  	@Override
40  	public int read() throws IOException {
41  		if (delegate == null) {
42  			initDelegate();
43  		}
44  		return delegate.read();
45  	}
46  
47  	/**
48  	 * {@inheritDoc}
49  	 * <p>
50  	 * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
51  	 * {@link FileInputStream#read(byte[])}.
52  	 */
53  	@Override
54  	public int read(final byte[] b) throws IOException {
55  		if (delegate == null) {
56  			initDelegate();
57  		}
58  		return delegate.read(b);
59  	}
60  
61  	/**
62  	 * {@inheritDoc}
63  	 * <p>
64  	 * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
65  	 * {@link FileInputStream#read(byte[], int, int)}.
66  	 */
67  	@Override
68  	public int read(final byte[] b, final int off, final int len) throws IOException {
69  		if (delegate == null) {
70  			initDelegate();
71  		}
72  		return delegate.read(b, off, len);
73  	}
74  
75  	/**
76  	 * {@inheritDoc}
77  	 * <p>
78  	 * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
79  	 * {@link FileInputStream#readNBytes(byte[], int, int)}.
80  	 */
81  	@Override
82  	public int readNBytes(final byte[] b, final int off, final int len) throws IOException {
83  		if (delegate == null) {
84  			initDelegate();
85  		}
86  		return delegate.readNBytes(b, off, len);
87  	}
88  
89  	/**
90  	 * {@inheritDoc}
91  	 * <p>
92  	 * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
93  	 * {@link FileInputStream#readAllBytes()}.
94  	 */
95  	@Override
96  	public byte[] readAllBytes() throws IOException {
97  		if (delegate == null) {
98  			initDelegate();
99  		}
100 		return delegate.readAllBytes();
101 	}
102 
103 	/**
104 	 * {@inheritDoc}
105 	 * <p>
106 	 * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
107 	 * {@link FileInputStream#skip(long)}.
108 	 */
109 	@Override
110 	public long skip(final long n) throws IOException {
111 		if (delegate == null) {
112 			initDelegate();
113 		}
114 		return delegate.skip(n);
115 	}
116 
117 	/**
118 	 * {@inheritDoc}
119 	 * <p>
120 	 * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
121 	 * {@link FileInputStream#available()}.
122 	 */
123 	@Override
124 	public int available() throws IOException {
125 		if (delegate == null) {
126 			initDelegate();
127 		}
128 		return delegate.available();
129 	}
130 
131 	/**
132 	 * {@inheritDoc}
133 	 * <p>
134 	 * <strong>This implementation</strong> calls {@link FileInputStream#close()} on the delegate and unassignes the
135 	 * delegate.
136 	 */
137 	@Override
138 	public void close() throws IOException {
139 		if (delegate != null) {
140 			delegate.close();
141 			delegate = null;
142 		}
143 	}
144 
145 	/**
146 	 * Initializes the delegate if not already done and delegates to {@link FileInputStream#getChannel()}.
147 	 *
148 	 * @return {@link FileInputStream#getChannel()}
149 	 * @throws FileNotFoundException see {@link FileInputStream#FileInputStream(File)}.
150 	 */
151 	public FileChannel getChannel() throws FileNotFoundException {
152 		if (delegate == null) {
153 			initDelegate();
154 		}
155 		return delegate.getChannel();
156 	}
157 
158 	/**
159 	 * Initializes the delegate if not already done and delegates to {@link FileInputStream#getFD()}.
160 	 *
161 	 * @return {@link FileInputStream#getFD()}
162 	 * @throws IOException see {@link FileInputStream#getFD()}
163 	 */
164 	public final FileDescriptor getFD() throws IOException {
165 		if (delegate == null) {
166 			initDelegate();
167 		}
168 		return delegate.getFD();
169 	}
170 
171 	/**
172 	 * {@inheritDoc}
173 	 * <p>
174 	 * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
175 	 * {@link FileInputStream#transferTo(OutputStream)}.
176 	 */
177 	@Override
178 	public long transferTo(final OutputStream out) throws IOException {
179 		if (delegate == null) {
180 			initDelegate();
181 		}
182 		return delegate.transferTo(out);
183 	}
184 
185 	/**
186 	 * Tell if the delegate is initialized.
187 	 *
188 	 * @return {@code true} if there is a delegate.
189 	 */
190 	public boolean isOpen() {
191 		return delegate != null;
192 	}
193 
194 	private void initDelegate() throws FileNotFoundException {
195 		delegate = new FileInputStream(file);
196 	}
197 
198 }