1 /*
2 * dpkg - Debian Package library and the Debian Package Maven plugin
3 * (c) Copyright 2016 Gerrit Hohl
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 package net.sourceforge.javadpkg.io.impl;
20
21 import java.io.File;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.io.InputStream;
25
26 import net.sourceforge.javadpkg.io.DataSource;
27 import net.sourceforge.javadpkg.io.Streams;
28
29 /**
30 * <p>
31 * A {@link DataSource} implementation based on a file.
32 * </p>
33 *
34 * @author Gerrit Hohl (gerrit-hohl@users.sourceforge.net)
35 * @version <b>1.0</b>, 26.04.2016 by Gerrit Hohl
36 */
37 public class DataFileSource implements DataSource {
38
39
40 /** The file. */
41 private File file;
42 /** The flag if the {@link #reset()} method will be supported. */
43 private boolean resettable;
44 /** The name of the source. */
45 private String name;
46 /** The stream. */
47 private InputStream in;
48 /**
49 * <p>
50 * The public stream which is returned by the {@link #getInputStream()}
51 * method.
52 * </p>
53 */
54 private UncloseableInputStream publicIn;
55 /** The flag if the stream is already open. */
56 private boolean opened;
57
58
59 /**
60 * <p>
61 * Creates a source.
62 * </p>
63 * <p>
64 * The stream on the file will be opened the first time the
65 * {@link #getInputStream()} method is called.
66 * </p>
67 *
68 * @param file
69 * The file.
70 * @param resettable
71 * The flag if the {@link #reset()} method will be supported.
72 * @throws IllegalArgumentException
73 * If the file is <code>null</code>.
74 */
75 public DataFileSource(File file, boolean resettable) {
76 super();
77
78 if (file == null)
79 throw new IllegalArgumentException("Argument file is null.");
80
81 this.file = file;
82 this.name = file.getAbsolutePath();
83 this.in = null;
84 this.publicIn = null;
85 this.opened = false;
86 this.resettable = resettable;
87 }
88
89
90 /**
91 * <p>
92 * Creates a source.
93 * </p>
94 * <p>
95 * The stream on the file will be opened the first time the
96 * {@link #getInputStream()} method is called.
97 * </p>
98 * <p>
99 * The {@link #reset()} method will be supported.
100 * </p>
101 *
102 * @param file
103 * The file.
104 * @throws IllegalArgumentException
105 * If the file is <code>null</code>.
106 */
107 public DataFileSource(File file) {
108 this(file, true);
109 }
110
111
112 @Override
113 public String getName() {
114 return this.name;
115 }
116
117
118 @Override
119 public long getLength() {
120 return this.file.length();
121 }
122
123
124 @Override
125 public boolean isResettable() {
126 return this.resettable;
127 }
128
129
130 @Override
131 public void reset() throws IOException {
132 if (!this.resettable)
133 throw new IOException("Source |" + this.name + "| doesn't support a reset.");
134 try {
135 if (this.in != null) {
136 this.in.close();
137 }
138 } finally {
139 this.in = null;
140 this.publicIn = null;
141 this.opened = false;
142 }
143 }
144
145
146 /**
147 * <p>
148 * Creates the {@link InputStream} which is returned by the
149 * {@link #getInputStream()} method.
150 * </p>
151 */
152 private void createPublicInputStream() {
153 this.publicIn = new UncloseableInputStream(this.in, new DelegateCloseHandler(this));
154 }
155
156
157 /**
158 * <p>
159 * Ensures that the stream is opened.
160 * </p>
161 *
162 * @throws IOException
163 * If an error occurs while opening the stream or if the source
164 * is already closed.
165 */
166 private void ensureInputStream() throws IOException {
167 if (this.in == null) {
168 if (!this.opened) {
169 try {
170 this.in = Streams.createBufferedFileInputStream(this.file);
171 } catch (FileNotFoundException e) {
172 throw new IOException("Couldn't open stream on source |" + this.name + "|: " + e.getMessage());
173 }
174 this.createPublicInputStream();
175 } else
176 throw new IOException("The stream of source |" + this.name + "| is already closed.");
177 }
178 }
179
180
181 @Override
182 public InputStream getInputStream() throws IOException {
183 this.ensureInputStream();
184 return this.publicIn;
185 }
186
187
188 @Override
189 public void close() throws IOException {
190 try {
191 if (this.in != null) {
192 this.in.close();
193 }
194 } finally {
195 this.publicIn = null;
196 this.in = null;
197 }
198 }
199
200
201 }