001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.vfs2;
018
019import java.io.Closeable;
020import java.net.URI;
021import java.net.URL;
022import java.nio.file.Path;
023import java.nio.file.Paths;
024import java.util.Comparator;
025import java.util.List;
026
027import org.apache.commons.vfs2.operations.FileOperations;
028
029/**
030 * Represents a file, and is used to access the content and structure of the file.
031 * <p>
032 * Files are arranged in a hierarchy. Each hierarchy forms a <em>file system</em>. A file system represents things like a
033 * local OS file system, a windows share, an HTTP server, or the contents of a Zip file.
034 * </p>
035 * <p>
036 * There are two types of files: <em>Folders</em>, which contain other files, and <em>normal files</em>, which contain data,
037 * or <em>content</em>. A folder may not have any content, and a normal file cannot contain other files.
038 * </p>
039 *
040 * <h2>File Naming</h2>
041 *
042 * <p>
043 * TODO - write this.
044 * </p>
045 *
046 * <h2>Reading and Writing a File</h2>
047 *
048 * <p>
049 * Reading and writing a file, and all other operations on the file's <em>content</em>, is done using the
050 * {@link FileContent} object returned by {@link #getContent}.
051 * </p>
052 *
053 * <h2>Creating and Deleting a File</h2>
054 *
055 * <p>
056 * A file is created using either {@link #createFolder}, {@link #createFile}, or by writing to the file using one of the
057 * {@link FileContent} methods.
058 * </p>
059 * <p>
060 * A file is deleted using {@link #delete}. Recursive deletion can be done using {@link #delete(FileSelector)}.
061 * </p>
062 *
063 * <h2>Finding Files</h2>
064 *
065 * <p>
066 * Other files in the <em>same</em> file system as this file can be found using:
067 * </p>
068 * <ul>
069 * <li>{@link #findFiles} to find a set of matching descendants in the same file system.</li>
070 * <li>{@link #getChildren} and {@link #getChild} to find the children of this file.</li>
071 * <li>{@link #getParent} to find the folder containing this file.</li>
072 * <li>{@link #getFileSystem} to find another file in the same file system.</li>
073 * <li>{@link #resolveFile} to find another file relative to this file.</li>
074 * </ul>
075 * <p>
076 * To find files in another file system, use a {@link FileSystemManager}.
077 * </p>
078 *
079 * <h2>Iterating Files</h2>
080 *
081 * <p>
082 * You can iterate over a FileObject using the Java "foreach" statement, which provides all descendants of a File
083 * Object.
084 * </p>
085 *
086 * <h2>Sorting Files</h2>
087 *
088 * <p>
089 * Files may be sorted using {@link java.util.Arrays#sort(Object[]) Arrays.sort()} and
090 * {@link List#sort(Comparator) List.sort()}.
091 * </p>
092 *
093 * @see FileSystemManager
094 * @see FileContent
095 * @see FileName
096 */
097public interface FileObject extends Comparable<FileObject>, Iterable<FileObject>, Closeable {
098
099    /**
100     * An empty immutable {@code FileObject} array.
101     *
102     * @since 2.8.0
103     */
104    FileObject[] EMPTY_ARRAY = {};
105
106    /**
107     * Closes the given file object.
108     *
109     * @param fileObject a file object, may be null.
110     * @throws FileSystemException See {@link FileObject#close()}.
111     * @since 2.11.0
112     */
113    static void close(final FileObject fileObject) throws FileSystemException {
114        if (fileObject != null) {
115            fileObject.close();
116        }
117    }
118
119    /**
120     * Queries the file if it is possible to rename it to newfile.
121     *
122     * @param newfile the new file(-name)
123     * @return true it this is the case
124     */
125    boolean canRenameTo(FileObject newfile);
126
127    /**
128     * Closes this file, and its content. This method is a hint to the implementation that it can release any resources
129     * associated with the file.
130     * <p>
131     * The file object can continue to be used after this method is called.
132     * </p>
133     *
134     * @throws FileSystemException On error closing the file.
135     * @see FileContent#close
136     */
137    @Override
138    void close() throws FileSystemException;
139
140    /**
141     * Copies another file, and all its descendants, to this file.
142     * <p>
143     * If this file does not exist, it is created. Its parent folder is also created, if necessary. If this file does
144     * exist, it is deleted first.
145     * </p>
146     * <p>
147     * This method is not transactional. If it fails and throws an exception, this file will potentially only be
148     * partially copied.
149     * </p>
150     *
151     * @param srcFile The source file to copy.
152     * @param selector The selector to use to select which files to copy.
153     * @throws FileSystemException If this file is read-only, or if the source file does not exist, or on error copying
154     *             the file.
155     */
156    void copyFrom(FileObject srcFile, FileSelector selector) throws FileSystemException;
157
158    /**
159     * Creates this file, if it does not exist. Also creates any ancestor folders which do not exist. This method does
160     * nothing if the file already exists and is a file.
161     *
162     * @throws FileSystemException If the file already exists with the wrong type, or the parent folder is read-only, or
163     *             on error creating this file or one of its ancestors.
164     */
165    void createFile() throws FileSystemException;
166
167    /**
168     * Creates this folder, if it does not exist. Also creates any ancestor folders which do not exist. This method does
169     * nothing if the folder already exists.
170     *
171     * @throws FileSystemException If the folder already exists with the wrong type, or the parent folder is read-only,
172     *             or on error creating this folder or one of its ancestors.
173     */
174    void createFolder() throws FileSystemException;
175
176    /**
177     * Deletes this file. Does nothing if this file does not exist of if it is a folder that has children. Does not
178     * delete any descendants of this file, use {@link #delete(FileSelector)} or {@link #deleteAll()} for that.
179     *
180     * @return true if this object has been deleted
181     * @throws FileSystemException If this file is a non-empty folder, or if this file is read-only, or on error
182     *             deleteing this file.
183     */
184    boolean delete() throws FileSystemException;
185
186    /**
187     * Deletes all descendants of this file that match a selector. Does nothing if this file does not exist.
188     *
189     * <p>
190     * This method is not transactional. If it fails and throws an exception, this file will potentially only be
191     * partially deleted.
192     * </p>
193     *
194     * @param selector The selector to use to select which files to delete.
195     * @return the number of deleted objects
196     * @throws FileSystemException If this file or one of its descendants is read-only, or on error deleting this file
197     *             or one of its descendants.
198     */
199    int delete(FileSelector selector) throws FileSystemException;
200
201    /**
202     * Deletes this file and all children.
203     *
204     * @return the number of deleted files.
205     * @throws FileSystemException if an error occurs.
206     * @see #delete(FileSelector)
207     * @see Selectors#SELECT_ALL
208     */
209    int deleteAll() throws FileSystemException;
210
211    /**
212     * Determines if this file exists.
213     *
214     * @return {@code true} if this file exists, {@code false} if not.
215     * @throws FileSystemException On error determining if this file exists.
216     */
217    boolean exists() throws FileSystemException;
218
219    /**
220     * Finds the set of matching descendants of this file, in depthwise order.
221     *
222     * @param selector The selector to use to select matching files.
223     * @return The matching files. The files are returned in depthwise order (that is, a child appears in the list
224     *         before its parent).
225     * @throws FileSystemException if an error occurs.
226     */
227    FileObject[] findFiles(FileSelector selector) throws FileSystemException;
228
229    /**
230     * Finds the set of matching descendants of this file.
231     *
232     * @param selector the selector used to determine if the file should be selected
233     * @param depthwise controls the ordering in the list. e.g. deepest first
234     * @param selected container for selected files. list needs not to be empty.
235     * @throws FileSystemException if an error occurs.
236     */
237    void findFiles(FileSelector selector, boolean depthwise, List<FileObject> selected) throws FileSystemException;
238
239    /**
240     * Gets a child of this file. Note that this method returns {@code null} when the child does not exist. This
241     * differs from {@link #resolveFile(String, NameScope)} which never returns null.
242     *
243     * @param name The name of the child.
244     * @return The child, or null if there is no such child.
245     * @throws FileSystemException If this file does not exist, or is not a folder, or on error determining this file's
246     *             children.
247     */
248    FileObject getChild(String name) throws FileSystemException;
249
250    /**
251     * Gets a lists of children of this file.
252     *
253     * @return An array containing the children of this file. The array is unordered. If the file does not have any
254     *         children, a zero-length array is returned. This method never returns null.
255     * @throws FileSystemException If this file does not exist, or is not a folder, or on error listing this file's
256     *             children.
257     */
258    FileObject[] getChildren() throws FileSystemException;
259
260    /**
261     * Gets this file's content. The {@link FileContent} returned by this method can be used to read and write the
262     * content of the file.
263     *
264     * <p>
265     * This method can be called if the file does not exist, and the returned {@link FileContent} can be used to create
266     * the file by writing its content.
267     * </p>
268     *
269     * @return This file's content.
270     * @throws FileSystemException On error getting this file's content.
271     */
272    FileContent getContent() throws FileSystemException;
273
274    /**
275     * Gets this instance's FileOperations.
276     *
277     * @return FileOperations interface that provides access to the operations API.
278     * @throws FileSystemException if an error occurs.
279     */
280    FileOperations getFileOperations() throws FileSystemException;
281
282    /**
283     * Gets the file system that contains this file.
284     *
285     * @return The file system.
286     */
287    FileSystem getFileSystem();
288
289    /**
290     * Gets the name of this file.
291     *
292     * @return the FileName, not {@code null}.
293     */
294    FileName getName();
295
296    /**
297     * Gets the folder that contains this file.
298     *
299     * @return The folder that contains this file. Returns null if this file is the root of a file system.
300     * @throws FileSystemException On error finding the file's parent.
301     */
302    FileObject getParent() throws FileSystemException;
303
304    /**
305     * Gets a Path representing this file.
306     *
307     * @return the Path for the file.
308     * @since 2.7.0
309     */
310    default Path getPath() {
311        return Paths.get(getURI());
312    }
313
314    /**
315     * Gets the receiver as a URI String for public display, like, without a password.
316     *
317     * @return A URI String without a password, never {@code null}.
318     */
319    String getPublicURIString();
320
321    /**
322     * Gets this file's type.
323     *
324     * @return One of the {@link FileType} constants. Never returns null.
325     * @throws FileSystemException On error determining the file's type.
326     */
327    FileType getType() throws FileSystemException;
328
329    /**
330     * Gets a URI representing this file.
331     *
332     * @return the URI for the file, not {@code null}.
333     * @since 2.7.0
334     */
335    default URI getURI() {
336        return URI.create(URI.create(getName().getURI()).toASCIIString());
337    }
338
339    /**
340     * Gets a URL representing this file.
341     *
342     * @return the URL for the file.
343     * @throws FileSystemException if an error occurs.
344     */
345    URL getURL() throws FileSystemException;
346
347    /**
348     * Tests whether the fileObject is attached.
349     *
350     * @return true if the FileObject is attached.
351     */
352    boolean isAttached();
353
354    /**
355     * Tests whether someone reads/write to this file.
356     *
357     * @return true if the file content is open.
358     */
359    boolean isContentOpen();
360
361    /**
362     * Tests whether this file is executable.
363     *
364     * @return {@code true} if this file is executable, {@code false} if not.
365     * @throws FileSystemException On error determining if this file exists.
366     */
367    boolean isExecutable() throws FileSystemException;
368
369    /**
370     * Tests whether this file is a regular file.
371     *
372     * @return true if this file is a regular file.
373     * @throws FileSystemException if an error occurs.
374     * @see #getType()
375     * @see FileType#FILE
376     * @since 2.1
377     */
378    boolean isFile() throws FileSystemException;
379
380    /**
381     * Tests whether this file is a folder.
382     *
383     * @return true if this file is a folder.
384     * @throws FileSystemException if an error occurs.
385     * @see #getType()
386     * @see FileType#FOLDER
387     * @since 2.1
388     */
389    boolean isFolder() throws FileSystemException;
390
391    /**
392     * Tests whether this file is hidden.
393     *
394     * @return {@code true} if this file is hidden, {@code false} if not.
395     * @throws FileSystemException On error determining if this file exists.
396     */
397    boolean isHidden() throws FileSystemException;
398
399    /**
400     * Tests whether this file can be read.
401     *
402     * @return {@code true} if this file is readable, {@code false} if not.
403     * @throws FileSystemException On error determining if this file exists.
404     */
405    boolean isReadable() throws FileSystemException;
406
407    /**
408     * Tests whether this file is a symbolic link.
409     *
410     * @return {@code true} if this file is a symbolic link, {@code false} if not.
411     * @throws FileSystemException On error determining if this file exists.
412     * @since 2.4
413     */
414    @SuppressWarnings("unused") // FileSystemException actually thrown in implementations.
415    default boolean isSymbolicLink() throws FileSystemException {
416        return false;
417    }
418
419    /**
420     * Tests whether this file can be written to.
421     *
422     * @return {@code true} if this file is writable, {@code false} if not.
423     * @throws FileSystemException On error determining if this file exists.
424     */
425    boolean isWriteable() throws FileSystemException;
426
427    /**
428     * Move this file.
429     *
430     * <p>
431     * If the destFile exists, it is deleted first.
432     * </p>
433     *
434     * @param destFile the New file name.
435     * @throws FileSystemException If this file is read-only, or if the source file does not exist, or on error copying
436     *             the file.
437     */
438    void moveTo(FileObject destFile) throws FileSystemException;
439
440    /**
441     * This will prepare the fileObject to get resynchronized with the underlying file system if required.
442     *
443     * @throws FileSystemException if an error occurs.
444     */
445    void refresh() throws FileSystemException;
446
447    /**
448     * Finds a file, relative to this file. Equivalent to calling {@code resolveFile( path, NameScope.FILE_SYSTEM )}.
449     *
450     * @param path The path of the file to locate. Can either be a relative path or an absolute path.
451     * @return The file.
452     * @throws FileSystemException On error parsing the path, or on error finding the file.
453     */
454    FileObject resolveFile(String path) throws FileSystemException;
455
456    /**
457     * Finds a file relative to this file.
458     *
459     * Refer to {@link NameScope} for a description of how names are resolved in the different scopes.
460     *
461     * @param name The name to resolve.
462     * @param scope the NameScope for the file.
463     * @return The file.
464     * @throws FileSystemException On error parsing the path, or on error finding the file.
465     */
466    FileObject resolveFile(String name, NameScope scope) throws FileSystemException;
467
468    /**
469     * Sets the owner's (or everybody's) write permission.
470     *
471     * @param executable True to allow read access, false to disallow.
472     * @param ownerOnly If {@code true}, the permission applies only to the owner; otherwise, it applies to everybody.
473     * @return true if the operation succeeded.
474     * @throws FileSystemException On error determining if this file exists.
475     * @since 2.1
476     */
477    boolean setExecutable(boolean executable, boolean ownerOnly) throws FileSystemException;
478
479    /**
480     * Sets the owner's (or everybody's) read permission.
481     *
482     * @param readable True to allow read access, false to disallow
483     * @param ownerOnly If {@code true}, the permission applies only to the owner; otherwise, it applies to everybody.
484     * @return true if the operation succeeded
485     * @throws FileSystemException On error determining if this file exists.
486     * @since 2.1
487     */
488    boolean setReadable(boolean readable, boolean ownerOnly) throws FileSystemException;
489
490    /**
491     * Sets the owner's (or everybody's) write permission.
492     *
493     * @param writable True to allow read access, false to disallow
494     * @param ownerOnly If {@code true}, the permission applies only to the owner; otherwise, it applies to everybody.
495     * @return true if the operation succeeded
496     * @throws FileSystemException On error determining if this file exists.
497     * @since 2.1
498     */
499    boolean setWritable(boolean writable, boolean ownerOnly) throws FileSystemException;
500}