1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.vfs2;
18
19 import java.io.Closeable;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.nio.charset.Charset;
24 import java.security.cert.Certificate;
25 import java.util.Arrays;
26 import java.util.Map;
27
28 import org.apache.commons.vfs2.provider.AbstractFileObject;
29 import org.apache.commons.vfs2.util.RandomAccessMode;
30
31 /**
32 * Represents the data content of a file.
33 * <p>
34 * To read from a file, use the {@code InputStream} returned by {@link #getInputStream()}.
35 * </p>
36 * <p>
37 * To write to a file, use the {@code OutputStream} returned by {@link #getOutputStream()} method. This will create the
38 * file, and the parent folder, if necessary.
39 * </p>
40 * <p>
41 * A file may have multiple InputStreams open at the same time.
42 * </p>
43 *
44 * @see FileObject#getContent
45 */
46 public interface FileContent extends Closeable {
47
48 /**
49 * Closes all resources used by the content, including any open stream. Commits pending changes to the file.
50 * <p>
51 * This method is a hint to the implementation that it can release resources. This object can continue to be used
52 * after calling this method.
53 * </p>
54 *
55 * @throws FileSystemException if an error occurs closing the file.
56 */
57 @Override
58 void close() throws FileSystemException;
59
60 /**
61 * Gets the value of an attribute of the file's content.
62 *
63 * @param attrName The name of the attribute. Attribute names are case insensitive.
64 * @return The value of the attribute, or null if the attribute value is unknown.
65 * @throws FileSystemException If the file does not exist, or does not support attributes.
66 */
67 Object getAttribute(String attrName) throws FileSystemException;
68
69 /**
70 * Gets the attributes of the file's content.
71 *
72 * @return The names of the attributes. Never returns null;
73 * @throws FileSystemException If the file does not exist, or does not support attributes.
74 */
75 String[] getAttributeNames() throws FileSystemException;
76
77 /**
78 * Returns a read-only map of this file's attributes.
79 *
80 * @return The attribute Map.
81 * @throws FileSystemException If the file does not exist, or does not support attributes.
82 */
83 Map<String, Object> getAttributes() throws FileSystemException;
84
85 /**
86 * Returns the content of a file as a byte array.
87 *
88 * @return The content as a byte array.
89 * @throws IOException if the file content cannot be accessed.
90 * @since 2.4
91 */
92 default byte[] getByteArray() throws IOException {
93 final long sizeL = getSize();
94 if (sizeL > Integer.MAX_VALUE) {
95 throw new IllegalStateException(String.format("File content is too large for a byte array: %,d", sizeL));
96 }
97 final boolean sizeUndefined = sizeL < 0;
98 final int size = sizeUndefined ? AbstractFileObject.DEFAULT_BUFFER_SIZE : (int) sizeL;
99 final byte[] buf = new byte[size];
100 int pos;
101 try (final InputStream in = getInputStream(size)) {
102 int read = 0;
103 for (pos = 0; pos < size && read >= 0; pos += read) {
104 read = in.read(buf, pos, size - pos);
105 }
106 }
107 return sizeUndefined && pos < buf.length ? Arrays.copyOf(buf, ++pos) : buf;
108 }
109
110 /**
111 * Gets the certificates if any used to sign this file or folder.
112 *
113 * @return The certificates, or an empty array if there are no certificates or the file does not support signing.
114 * @throws FileSystemException If the file does not exist, or is being written.
115 */
116 Certificate[] getCertificates() throws FileSystemException;
117
118 /**
119 * Gets the content info. e.g. type, encoding, ...
120 *
121 * @return the FileContentInfo
122 * @throws FileSystemException if an error occurs.
123 */
124 FileContentInfo getContentInfo() throws FileSystemException;
125
126 /**
127 * Gets the file which this is the content of.
128 *
129 * @return The FileObject this is the content of.
130 */
131 FileObject getFile();
132
133 /**
134 * Gets an input stream for reading the file's content.
135 * <p>
136 * There may only be a single input or output stream open for the file at any time.
137 * </p>
138 *
139 * @return An input stream to read the file's content from. The input stream is buffered, so there is no need to
140 * wrap it in a {@code BufferedInputStream}.
141 * @throws FileSystemException If the file does not exist, or is being read, or is being written, or on error
142 * opening the stream.
143 */
144 InputStream getInputStream() throws FileSystemException;
145
146 /**
147 * Gets an input stream for reading the file's content.
148 * <p>
149 * There may only be a single input or output stream open for the file at any time.
150 * </p>
151 *
152 * @param bufferSize The buffer size to use.
153 * @return An input stream to read the file's content from. The input stream is buffered, so there is no need to
154 * wrap it in a {@code BufferedInputStream}.
155 * @throws FileSystemException If the file does not exist, or is being read, or is being written, or on error
156 * opening the stream.
157 * @since 2.4
158 */
159 default InputStream getInputStream(final int bufferSize) throws FileSystemException {
160 return getInputStream();
161 }
162
163 /**
164 * Gets the last-modified timestamp of the file.
165 *
166 * @return The last-modified timestamp.
167 * @throws FileSystemException If the file does not exist, or is being written to, or on error determining the
168 * last-modified timestamp.
169 */
170 long getLastModifiedTime() throws FileSystemException;
171
172 /**
173 * Gets an output stream for writing the file's content.
174 * <p>
175 * If the file does not exist, this method creates it, and the parent folder, if necessary. If the file does exist,
176 * it is replaced with whatever is written to the output stream.
177 * </p>
178 * <p>
179 * There may only be a single input or output stream open for the file at any time.
180 * </p>
181 *
182 * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it
183 * in a {@code BufferedOutputStream}.
184 * @throws FileSystemException If the file is read-only, or is being read, or is being written, or on error opening
185 * the stream.
186 */
187 OutputStream getOutputStream() throws FileSystemException;
188
189 /**
190 * Gets an output stream for writing the file's content.
191 * <p>
192 * If the file does not exist, this method creates it, and the parent folder, if necessary. If the file does exist,
193 * it is replaced with whatever is written to the output stream.
194 * </p>
195 * <p>
196 * There may only be a single input or output stream open for the file at any time.
197 * </p>
198 *
199 * @param bAppend true if you would like to append to the file. This may not be supported by all implementations.
200 * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it
201 * in a {@code BufferedOutputStream}.
202 * @throws FileSystemException If the file is read-only, or is being read, or is being written, or bAppend is true
203 * and the implementation does not support it, or on error opening the stream.
204 */
205 OutputStream getOutputStream(boolean bAppend) throws FileSystemException;
206
207 /**
208 * Gets an output stream for writing the file's content.
209 * <p>
210 * If the file does not exist, this method creates it, and the parent folder, if necessary. If the file does exist,
211 * it is replaced with whatever is written to the output stream.
212 * </p>
213 * <p>
214 * There may only be a single input or output stream open for the file at any time.
215 * </p>
216 *
217 * @param bAppend true if you would like to append to the file. This may not be supported by all implementations.
218 * @param bufferSize The buffer size to use.
219 * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it
220 * in a {@code BufferedOutputStream}.
221 * @throws FileSystemException If the file is read-only, or is being read, or is being written, or bAppend is true
222 * and the implementation does not support it, or on error opening the stream.
223 * @since 2.4
224 */
225 default OutputStream getOutputStream(final boolean bAppend, final int bufferSize) throws FileSystemException {
226 return getOutputStream(bAppend);
227 }
228
229 /**
230 * Gets an output stream for writing the file's content.
231 * <p>
232 * If the file does not exist, this method creates it, and the parent folder, if necessary. If the file does exist,
233 * it is replaced with whatever is written to the output stream.
234 * </p>
235 * <p>
236 * There may only be a single input or output stream open for the file at any time.
237 * </p>
238 *
239 * @param bufferSize The buffer size to use.
240 * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it
241 * in a {@code BufferedOutputStream}.
242 * @throws FileSystemException If the file is read-only, or is being read, or is being written, or bAppend is true
243 * and the implementation does not support it, or on error opening the stream.
244 * @since 2.4
245 */
246 default OutputStream getOutputStream(final int bufferSize) throws FileSystemException {
247 return getOutputStream();
248 }
249
250 /**
251 * Gets an stream for reading/writing the file's content.
252 * <p>
253 * If the file does not exist, and you use one of the write* methods, this method creates it, and the parent folder,
254 * if necessary. If the file does exist, parts of the file are replaced with whatever is written at a given
255 * position.
256 * </p>
257 * <p>
258 * There may only be a single input or output stream open for the file at any time.
259 * </p>
260 *
261 * @param mode The mode to use to access the file.
262 * @return the stream for reading and writing the file's content.
263 * @throws FileSystemException If the file is read-only, or is being read, or is being written, or on error opening
264 * the stream.
265 */
266 RandomAccessContent getRandomAccessContent(final RandomAccessMode mode) throws FileSystemException;
267
268 /**
269 * Gets the size of the file, in bytes.
270 *
271 * @return The size of the file, in bytes.
272 * @throws FileSystemException If the file does not exist, or is being written to, or on error determining the size.
273 */
274 long getSize() throws FileSystemException;
275
276 /**
277 * Returns the content of a file as a String.
278 *
279 * @param charset The file character set, may be null.
280 * @return The content as a byte array.
281 * @throws IOException if the file content cannot be accessed.
282 * @since 2.4
283 */
284 default String getString(final Charset charset) throws IOException {
285 return new String(getByteArray(), charset == null ? Charset.defaultCharset() : charset);
286 }
287
288 /**
289 * Gets the content of a file as a String.
290 *
291 * @param charset The file character set, may be null.
292 * @return The content as a byte array.
293 * @throws IOException if the file content cannot be accessed.
294 * @since 2.4
295 */
296 default String getString(final String charset) throws IOException {
297 return new String(getByteArray(), charset == null ? Charset.defaultCharset().name() : charset);
298 }
299
300 /**
301 * Checks if an attribute of the file's content exists.
302 *
303 * @param attrName The name of the attribute.
304 * @return true if the attribute exists, false otherwise.
305 * @throws FileSystemException If the file does not exist, or does not support attributes.
306 */
307 boolean hasAttribute(String attrName) throws FileSystemException;
308
309 /**
310 * Checks if the receiver is empty.
311 *
312 * @return true if the receiver is empty, false otherwise.
313 * @throws FileSystemException If the file does not exist, or is being written to, or on error determining the size.
314 * @since 2.5.0
315 */
316 default boolean isEmpty() throws FileSystemException {
317 return getSize() <= 0;
318 }
319
320 /**
321 * Checks if this file has open streams.
322 *
323 * @return true if the file is open, false otherwise.
324 */
325 boolean isOpen();
326
327 /**
328 * Removes the value of an attribute of the file's content.
329 *
330 * @param attrName The name of the attribute.
331 * @throws FileSystemException If the file does not exist, or is read-only, or does not support attributes, or on
332 * error removing the attribute.
333 */
334 void removeAttribute(String attrName) throws FileSystemException;
335
336 /**
337 * Sets the value of an attribute of the file's content. Creates the file if it does not exist.
338 *
339 * @param attrName The name of the attribute.
340 * @param value The value of the attribute.
341 * @throws FileSystemException If the file does not exist, or is read-only, or does not support attributes, or on
342 * error setting the attribute.
343 */
344 void setAttribute(String attrName, Object value) throws FileSystemException;
345
346 /**
347 * Sets the last-modified timestamp of the file. Creates the file if it does not exist.
348 *
349 * @param modTime The time to set the last-modified timestamp to.
350 * @throws FileSystemException If the file is read-only, or is being written to, or on error setting the
351 * last-modified timestamp.
352 */
353 void setLastModifiedTime(long modTime) throws FileSystemException;
354
355 /**
356 * Writes this content to another FileContent.
357 *
358 * @param output The target OutputStream.
359 * @throws IOException if an error occurs writing the content.
360 * @return the total number of bytes written
361 * @since 2.1
362 */
363 long write(FileContent output) throws IOException;
364
365 /**
366 * Writes this content to another FileObject.
367 *
368 * @param file The target FileObject.
369 * @throws IOException if an error occurs writing the content.
370 * @return the total number of bytes written
371 * @since 2.1
372 */
373 long write(FileObject file) throws IOException;
374
375 /**
376 * Writes this content to an OutputStream.
377 *
378 * @param output The target OutputStream.
379 * @return the total number of bytes written
380 * @throws IOException if an error occurs writing the content.
381 * @since 2.1
382 */
383 long write(OutputStream output) throws IOException;
384
385 /**
386 * Writes this content to an OutputStream.
387 *
388 * @param output The target OutputStream.
389 * @param bufferSize The buffer size to write data chunks.
390 * @return the total number of bytes written
391 * @throws IOException if an error occurs writing the file.
392 * @since 2.1
393 */
394 long write(OutputStream output, int bufferSize) throws IOException;
395
396 }