View Javadoc
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       * Lists 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      * Retrieves 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      * get 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      * Returns 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      * Returns 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      * Returns 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      * Determines 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      * Returns 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      * Returns 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      * Returns 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      * Returns 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      * Returns 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      * Determines 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      * Returns 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 }