/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.vfs2.provider;

import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.vfs2.Capability;
import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileContentInfoFactory;
import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileNotFolderException;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSelector;
import org.apache.commons.vfs2.FileSystem;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.NameScope;
import org.apache.commons.vfs2.RandomAccessContent;
import org.apache.commons.vfs2.Selectors;
import org.apache.commons.vfs2.operations.DefaultFileOperations;
import org.apache.commons.vfs2.operations.FileOperations;
import org.apache.commons.vfs2.util.FileObjectUtils;
import org.apache.commons.vfs2.util.RandomAccessMode;

/**
 * A partial file object implementation.
 *
 * TODO - Chop this class up - move all the protected methods to several interfaces, so that structure and content can
 * be separately overridden.
 *
 * <p>
 * TODO - Check caps in methods like getChildren(), etc, and give better error messages (eg 'this file type does not
 * support listing children', vs 'this is not a folder')
 * </p>
 *
 * @param <AFS> An AbstractFileSystem subclass
 */
public abstract class AbstractFileObject<AFS extends AbstractFileSystem> implements FileObject {

    private static final FileName[] EMPTY_FILE_NAME_ARRAY = new FileName[0];

    private static final String DO_GET_INPUT_STREAM_INT = "doGetInputStream(int)";

    /**
     * Same as {@link BufferedInputStream}.
     */
    public static final int DEFAULT_BUFFER_SIZE = 8192;

    private static final FileName[] EMPTY_FILE_ARRAY = {};

    private static final int INITIAL_LIST_SIZE = 5;

    /**
     * Traverses a file.
     */
    private static void traverse(final DefaultFileSelectorInfo fileInfo, final FileSelector selector,
            final boolean depthwise, final List<FileObject> selected) throws Exception {
        // Check the file itself
        final FileObject file = fileInfo.getFile();
        final int index = selected.size();

        // If the file is a folder, traverse it
        if (file.getType().hasChildren() && selector.traverseDescendents(fileInfo)) {
            final int curDepth = fileInfo.getDepth();
            fileInfo.setDepth(curDepth + 1);

            // Traverse the children
            final FileObject[] children = file.getChildren();
            for (final FileObject child : children) {
                fileInfo.setFile(child);
                traverse(fileInfo, selector, depthwise, selected);
            }

            fileInfo.setFile(file);
            fileInfo.setDepth(curDepth);
        }

        // Add the file if doing depthwise traversal
        if (selector.includeFile(fileInfo)) {
            if (depthwise) {
                // Add this file after its descendants
                selected.add(file);
            } else {
                // Add this file before its descendants
                selected.add(index, file);
            }
        }
    }
    private final AbstractFileName fileName;

    private final AFS fileSystem;
    private FileContent content;
    // Cached info
    private boolean attached;

    private FileType type;
    private FileObject parent;

    // Changed to hold only the name of the children and let the object
    // go into the global files cache
    // private FileObject[] children;
    private FileName[] children;

    private List<Object> objects;

    /**
     * FileServices instance.
     */
    private FileOperations operations;

    /**
     *
     * @param name the file name - muse be an instance of {@link AbstractFileName}
     * @param fileSystem the file system
     * @throws ClassCastException if {@code name} is not an instance of {@link AbstractFileName}
     */
    protected AbstractFileObject(final AbstractFileName name, final AFS fileSystem) {
        this.fileName = name;
        this.fileSystem = fileSystem;
        fileSystem.fileObjectHanded(this);
    }

    /**
     * Attaches to the file.
     *
     * @throws FileSystemException if an error occurs.
     */
    private void attach() throws FileSystemException {
        synchronized (fileSystem) {
            if (attached) {
                return;
            }

            try {
                // Attach and determine the file type
                doAttach();
                attached = true;
                // now the type could already be injected by doAttach (e.g from parent to child)

                /*
                 * VFS-210: determine the type when really asked fore if (type == null) { setFileType(doGetType()); } if
                 * (type == null) { setFileType(FileType.IMAGINARY); }
                 */
            } catch (final Exception exc) {
                throw new FileSystemException("vfs.provider/get-type.error", exc, fileName);
            }

            // fs.fileAttached(this);
        }
    }

    /**
     * Queries the object if a simple rename to the file name of {@code newfile} is possible.
     *
     * @param newfile the new file name
     * @return true if rename is possible
     */
    @Override
    public boolean canRenameTo(final FileObject newfile) {
        return fileSystem == newfile.getFileSystem();
    }

    /**
     * Notifies the file that its children have changed.
     *
     * @param childName The name of the child.
     * @param newType The type of the child.
     * @throws Exception if an error occurs.
     */
    protected void childrenChanged(final FileName childName, final FileType newType) throws Exception {
        // TODO - this may be called when not attached

        if (children != null && childName != null && newType != null) {
            // TODO - figure out if children[] can be replaced by list
            final ArrayList<FileName> list = new ArrayList<>(Arrays.asList(children));
            if (newType.equals(FileType.IMAGINARY)) {
                list.remove(childName);
            } else {
                list.add(childName);
            }
            children = list.toArray(EMPTY_FILE_NAME_ARRAY);
        }

        // removeChildrenCache();
        onChildrenChanged(childName, newType);
    }

    /**
     * Closes this file, and its content.
     *
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public void close() throws FileSystemException {
        FileSystemException exc = null;

        synchronized (fileSystem) {
            // Close the content
            if (content != null) {
                try {
                    content.close();
                    content = null;
                } catch (final FileSystemException e) {
                    exc = e;
                }
            }

            // Detach from the file
            try {
                detach();
            } catch (final Exception e) {
                exc = new FileSystemException("vfs.provider/close.error", fileName, e);
            }

            if (exc != null) {
                throw exc;
            }
        }
    }

    /**
     * Compares two FileObjects (ignores case).
     *
     * @param file the object to compare.
     * @return a negative integer, zero, or a positive integer when this object is less than, equal to, or greater than
     *         the given object.
     */
    @Override
    public int compareTo(final FileObject file) {
        if (file == null) {
            return 1;
        }
        return this.toString().compareToIgnoreCase(file.toString());
    }

    /**
     * Copies another file to this file.
     *
     * @param file The FileObject to copy.
     * @param selector The FileSelector.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public void copyFrom(final FileObject file, final FileSelector selector) throws FileSystemException {
        if (!FileObjectUtils.exists(file)) {
            throw new FileSystemException("vfs.provider/copy-missing-file.error", file);
        }

        // Locate the files to copy across
        final ArrayList<FileObject> files = new ArrayList<>();
        file.findFiles(selector, false, files);

        // Copy everything across
        for (final FileObject srcFile : files) {
            // Determine the destination file
            final String relPath = file.getName().getRelativeName(srcFile.getName());
            final FileObject destFile = resolveFile(relPath, NameScope.DESCENDENT_OR_SELF);

            // Clean up the destination file, if necessary
            if (FileObjectUtils.exists(destFile) && destFile.getType() != srcFile.getType()) {
                // The destination file exists, and is not of the same type,
                // so delete it
                // TODO - add a pluggable policy for deleting and overwriting existing files
                destFile.deleteAll();
            }

            // Copy across
            try {
                if (srcFile.getType().hasContent()) {
                    FileObjectUtils.writeContent(srcFile, destFile);
                } else if (srcFile.getType().hasChildren()) {
                    destFile.createFolder();
                }
            } catch (final IOException e) {
                throw new FileSystemException("vfs.provider/copy-file.error", e, srcFile, destFile);
            }
        }
    }

    /**
     * Creates this file, if it does not exist.
     *
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public void createFile() throws FileSystemException {
        synchronized (fileSystem) {
            try {
                // VFS-210: We do not want to trunc any existing file, checking for its existence is
                // still required
                if (exists() && !isFile()) {
                    throw new FileSystemException("vfs.provider/create-file.error", fileName);
                }

                if (!exists()) {
                    getOutputStream().close();
                    endOutput();
                }
            } catch (final RuntimeException re) {
                throw re;
            } catch (final Exception e) {
                throw new FileSystemException("vfs.provider/create-file.error", fileName, e);
            }
        }
    }

    /**
     * Creates this folder, if it does not exist. Also creates any ancestor files which do not exist.
     *
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public void createFolder() throws FileSystemException {
        synchronized (fileSystem) {
            // VFS-210: we create a folder only if it does not already exist. So this check should be safe.
            if (getType().hasChildren()) {
                // Already exists as correct type
                return;
            }
            if (getType() != FileType.IMAGINARY) {
                throw new FileSystemException("vfs.provider/create-folder-mismatched-type.error", fileName);
            }
            /*
             * VFS-210: checking for writeable is not always possible as the security constraint might be more complex
             * if (!isWriteable()) { throw new FileSystemException("vfs.provider/create-folder-read-only.error", name);
             * }
             */

            // Traverse up the hierarchy and make sure everything is a folder
            final FileObject parent = getParent();
            if (parent != null) {
                parent.createFolder();
            }

            try {
                // Create the folder
                doCreateFolder();

                // Update cached info
                handleCreate(FileType.FOLDER);
            } catch (final RuntimeException re) {
                throw re;
            } catch (final Exception exc) {
                throw new FileSystemException("vfs.provider/create-folder.error", fileName, exc);
            }
        }
    }

    /**
     * Deletes this file.
     * <p>
     * TODO - This will not fail if this is a non-empty folder.
     * </p>
     *
     * @return true if this object has been deleted
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public boolean delete() throws FileSystemException {
        return delete(Selectors.SELECT_SELF) > 0;
    }

    /**
     * Deletes this file, and all children matching the {@code selector}.
     *
     * @param selector The FileSelector.
     * @return the number of deleted files.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public int delete(final FileSelector selector) throws FileSystemException {
        int nuofDeleted = 0;

        /*
         * VFS-210 if (getType() == FileType.IMAGINARY) { // File does not exist return nuofDeleted; }
         */

        // Locate all the files to delete
        final ArrayList<FileObject> files = new ArrayList<>();
        findFiles(selector, true, files);

        // Delete 'em
        final int count = files.size();
        for (final FileObject fileObject : files) {
            final AbstractFileObject file = FileObjectUtils.getAbstractFileObject(fileObject);
            // file.attach();

            // VFS-210: It seems impossible to me that findFiles will return a list with hidden files/directories
            // in it, else it would not be hidden. Checking for the file-type seems ok in this case
            // If the file is a folder, make sure all its children have been deleted
            if (file.getType().hasChildren() && file.getChildren().length != 0) {
                // Skip - as the selector forced us not to delete all files
                continue;
            }

            // Delete the file
            if (file.deleteSelf()) {
                nuofDeleted++;
            }
        }

        return nuofDeleted;
    }

    /**
     * Deletes this file and all children. Shorthand for {@code delete(Selectors.SELECT_ALL)}
     *
     * @return the number of deleted files.
     * @throws FileSystemException if an error occurs.
     * @see #delete(FileSelector)
     * @see Selectors#SELECT_ALL
     */
    @Override
    public int deleteAll() throws FileSystemException {
        return this.delete(Selectors.SELECT_ALL);
    }

    /**
     * Deletes this file, once all its children have been deleted
     *
     * @return true if this file has been deleted
     * @throws FileSystemException if an error occurs.
     */
    private boolean deleteSelf() throws FileSystemException {
        synchronized (fileSystem) {
            // Its possible to delete a read-only file if you have write-execute access to the directory

            /*
             * VFS-210 if (getType() == FileType.IMAGINARY) { // File does not exist return false; }
             */

            try {
                // Delete the file
                doDelete();

                // Update cached info
                handleDelete();
            } catch (final RuntimeException re) {
                throw re;
            } catch (final Exception exc) {
                throw new FileSystemException("vfs.provider/delete.error", exc, fileName);
            }

            return true;
        }
    }

    /**
     * Detaches this file, invalidating all cached info. This will force a call to {@link #doAttach} next time this file
     * is used.
     *
     * @throws Exception if an error occurs.
     */
    private void detach() throws Exception {
        synchronized (fileSystem) {
            if (attached) {
                try {
                    doDetach();
                } finally {
                    attached = false;
                    setFileType(null);
                    parent = null;

                    // fs.fileDetached(this);

                    removeChildrenCache();
                    // children = null;
                }
            }
        }
    }

    /**
     * Attaches this file object to its file resource.
     * <p>
     * This method is called before any of the doBlah() or onBlah() methods. Sub-classes can use this method to perform
     * lazy initialization.
     * </p>
     * <p>
     * This implementation does nothing.
     * </p>
     *
     * @throws Exception if an error occurs.
     */
    protected void doAttach() throws Exception {
        // noop
    }

    /**
     * Create a FileContent implementation.
     *
     * @return The FileContent.
     * @throws FileSystemException if an error occurs.
     * @since 2.0
     */
    protected FileContent doCreateFileContent() throws FileSystemException {
        return new DefaultFileContent(this, getFileContentInfoFactory());
    }

    /**
     * Creates this file as a folder. Is only called when:
     * <ul>
     * <li>{@link #doGetType} returns {@link FileType#IMAGINARY}.</li>
     * <li>The parent folder exists and is writeable, or this file is the root of the file system.</li>
     * </ul>
     * This implementation throws an exception.
     *
     * @throws Exception if an error occurs.
     */
    protected void doCreateFolder() throws Exception {
        throw new FileSystemException("vfs.provider/create-folder-not-supported.error");
    }

    /**
     * Deletes the file. Is only called when:
     * <ul>
     * <li>{@link #doGetType} does not return {@link FileType#IMAGINARY}.</li>
     * <li>{@link #doIsWriteable} returns true.</li>
     * <li>This file has no children, if a folder.</li>
     * </ul>
     * This implementation throws an exception.
     *
     * @throws Exception if an error occurs.
     */
    protected void doDelete() throws Exception {
        throw new FileSystemException("vfs.provider/delete-not-supported.error");
    }

    /**
     * Detaches this file object from its file resource.
     * <p>
     * Called when this file is closed. Note that the file object may be reused later, so should be able to be
     * reattached.
     * </p>
     * <p>
     * This implementation does nothing.
     * </p>
     *
     * @throws Exception if an error occurs.
     */
    protected void doDetach() throws Exception {
        // noop
    }

    /**
     * Returns the attributes of this file. Is only called if {@link #doGetType} does not return
     * {@link FileType#IMAGINARY}.
     * <p>
     * This implementation always returns an empty map.
     * </p>
     *
     * @return The attributes of the file.
     * @throws Exception if an error occurs.
     */
    protected Map<String, Object> doGetAttributes() throws Exception {
        return Collections.emptyMap();
    }

    /**
     * Returns the certificates used to sign this file. Is only called if {@link #doGetType} does not return
     * {@link FileType#IMAGINARY}.
     * <p>
     * This implementation always returns null.
     * </p>
     *
     * @return The certificates used to sign the file.
     * @throws Exception if an error occurs.
     */
    protected Certificate[] doGetCertificates() throws Exception {
        return null;
    }

    /**
     * Returns the size of the file content (in bytes). Is only called if {@link #doGetType} returns
     * {@link FileType#FILE}.
     *
     * @return The size of the file in bytes.
     * @throws Exception if an error occurs.
     */
    protected abstract long doGetContentSize() throws Exception;

    /**
     * Creates an input stream to read the file content from. Is only called if {@link #doGetType} returns
     * {@link FileType#FILE}.
     * <p>
     * It is guaranteed that there are no open output streams for this file when this method is called.
     * </p>
     * <p>
     * The returned stream does not have to be buffered.
     * </p>
     *
     * @return An InputStream to read the file content.
     * @throws Exception if an error occurs.
     */
    protected InputStream doGetInputStream() throws Exception {
        // Backward compatibility.
        return doGetInputStream(DEFAULT_BUFFER_SIZE);
    }

    /**
     * Creates an input stream to read the file content from. Is only called if {@link #doGetType} returns
     * {@link FileType#FILE}.
     * <p>
     * It is guaranteed that there are no open output streams for this file when this method is called.
     * </p>
     * <p>
     * The returned stream does not have to be buffered.
     * </p>
     * @param bufferSize Buffer size hint.
     * @return An InputStream to read the file content.
     * @throws Exception if an error occurs.
     */
    protected InputStream doGetInputStream(final int bufferSize) throws Exception {
        throw new UnsupportedOperationException(DO_GET_INPUT_STREAM_INT);
    }

    /**
     * Returns the last modified time of this file. Is only called if {@link #doGetType} does not return
     * <p>
     * This implementation throws an exception.
     * </p>
     *
     * @return The last modification time.
     * @throws Exception if an error occurs.
     */
    protected long doGetLastModifiedTime() throws Exception {
        throw new FileSystemException("vfs.provider/get-last-modified-not-supported.error");
    }

    /**
     * Creates an output stream to write the file content to. Is only called if:
     * <ul>
     * <li>{@link #doIsWriteable} returns true.
     * <li>{@link #doGetType} returns {@link FileType#FILE}, or {@link #doGetType} returns {@link FileType#IMAGINARY},
     * and the file's parent exists and is a folder.
     * </ul>
     * It is guaranteed that there are no open stream (input or output) for this file when this method is called.
     * <p>
     * The returned stream does not have to be buffered.
     * </p>
     * <p>
     * This implementation throws an exception.
     * </p>
     *
     * @param bAppend true if the file should be appended to, false if it should be overwritten.
     * @return An OutputStream to write to the file.
     * @throws Exception if an error occurs.
     */
    protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
        throw new FileSystemException("vfs.provider/write-not-supported.error");
    }

    /**
     * Creates access to the file for random i/o. Is only called if {@link #doGetType} returns {@link FileType#FILE}.
     * <p>
     * It is guaranteed that there are no open output streams for this file when this method is called.
     * </p>
     *
     * @param mode The mode to access the file.
     * @return The RandomAccessContext.
     * @throws Exception if an error occurs.
     */
    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception {
        throw new FileSystemException("vfs.provider/random-access-not-supported.error");
    }

    /**
     * Determines the type of this file. Must not return null. The return value of this method is cached, so the
     * implementation can be expensive.
     *
     * @return the type of the file.
     * @throws Exception if an error occurs.
     */
    protected abstract FileType doGetType() throws Exception;

    /**
     * Determines if this file is executable. Is only called if {@link #doGetType} does not return
     * {@link FileType#IMAGINARY}.
     * <p>
     * This implementation always returns false.
     * </p>
     *
     * @return true if the file is executable, false otherwise.
     * @throws Exception if an error occurs.
     */
    protected boolean doIsExecutable() throws Exception {
        return false;
    }

    /**
     * Determines if this file is hidden. Is only called if {@link #doGetType} does not return
     * {@link FileType#IMAGINARY}.
     * <p>
     * This implementation always returns false.
     * </p>
     *
     * @return true if the file is hidden, false otherwise.
     * @throws Exception if an error occurs.
     */
    protected boolean doIsHidden() throws Exception {
        return false;
    }

    /**
     * Determines if this file can be read. Is only called if {@link #doGetType} does not return
     * {@link FileType#IMAGINARY}.
     * <p>
     * This implementation always returns true.
     * </p>
     *
     * @return true if the file is readable, false otherwise.
     * @throws Exception if an error occurs.
     */
    protected boolean doIsReadable() throws Exception {
        return true;
    }

    /**
     * Checks if this fileObject is the same file as {@code destFile} just with a different name. E.g. for case
     * insensitive file systems like windows.
     *
     * @param destFile The file to compare to.
     * @return true if the FileObjects are the same.
     * @throws FileSystemException if an error occurs.
     */
    protected boolean doIsSameFile(final FileObject destFile) throws FileSystemException {
        return false;
    }

    /**
     * Determines if this file is a symbolic link. Is only called if {@link #doGetType} does not return
     * {@link FileType#IMAGINARY}.
     * <p>
     * This implementation always returns false.
     * </p>
     *
     * @return true if the file is readable, false otherwise.
     * @throws Exception if an error occurs.
     * @since 2.4
     */
    protected boolean doIsSymbolicLink() throws Exception {
        return false;
    }

    /**
     * Determines if this file can be written to. Is only called if {@link #doGetType} does not return
     * {@link FileType#IMAGINARY}.
     * <p>
     * This implementation always returns true.
     * </p>
     *
     * @return true if the file is writable.
     * @throws Exception if an error occurs.
     */
    protected boolean doIsWriteable() throws Exception {
        return true;
    }

    /**
     * Lists the children of this file. Is only called if {@link #doGetType} returns {@link FileType#FOLDER}. The return
     * value of this method is cached, so the implementation can be expensive.
     *
     * @return a possible empty String array if the file is a directory or null or an exception if the file is not a
     *         directory or can't be read.
     * @throws Exception if an error occurs.
     */
    protected abstract String[] doListChildren() throws Exception;

    /**
     * Lists the children of this file.
     * <p>
     * Is only called if {@link #doGetType} returns {@link FileType#FOLDER}.
     * </p>
     * <p>
     * The return value of this method is cached, so the implementation can be expensive.
     * Other than {@code doListChildren} you could return FileObject's to e.g. reinitialize the type of the file.
     * </p>
     * <p>
     * (Introduced for Webdav: "permission denied on resource" during getType())
     * </p>
     *
     * @return The children of this FileObject.
     * @throws Exception if an error occurs.
     */
    protected FileObject[] doListChildrenResolved() throws Exception {
        return null;
    }

    /**
     * Removes an attribute of this file.
     * <p>
     * Is only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}.
     * </p>
     * <p>
     * This implementation throws an exception.
     * </p>
     *
     * @param attrName The name of the attribute to remove.
     * @throws Exception if an error occurs.
     * @since 2.0
     */
    protected void doRemoveAttribute(final String attrName) throws Exception {
        throw new FileSystemException("vfs.provider/remove-attribute-not-supported.error");
    }

    /**
     * Renames the file.
     * <p>
     * Is only called when:
     * </p>
     * <ul>
     * <li>{@link #doIsWriteable} returns true.</li>
     * </ul>
     * <p>
     * This implementation throws an exception.
     * </p>
     *
     * @param newFile A FileObject with the new file name.
     * @throws Exception if an error occurs.
     */
    protected void doRename(final FileObject newFile) throws Exception {
        throw new FileSystemException("vfs.provider/rename-not-supported.error");
    }

    /**
     * Sets an attribute of this file.
     * <p>
     * Is only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}.
     * </p>
     * <p>
     * This implementation throws an exception.
     * </p>
     *
     * @param attrName The attribute name.
     * @param value The value to be associated with the attribute name.
     * @throws Exception if an error occurs.
     */
    protected void doSetAttribute(final String attrName, final Object value) throws Exception {
        throw new FileSystemException("vfs.provider/set-attribute-not-supported.error");
    }

    /**
     * Make the file executable.
     * <p>
     * Only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}.
     * </p>
     * <p>
     * This implementation returns false.
     * </p>
     *
     * @param executable True to allow access, false to disallow.
     * @param ownerOnly If {@code true}, the permission applies only to the owner; otherwise, it applies to everybody.
     * @return true if the operation succeeded.
     * @throws Exception Any Exception thrown is wrapped in FileSystemException.
     * @see #setExecutable(boolean, boolean)
     * @since 2.1
     */
    protected boolean doSetExecutable(final boolean executable, final boolean ownerOnly) throws Exception {
        return false;
    }

    /**
     * Sets the last modified time of this file.
     * <p>
     * Is only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}.
     * </p>
     * <p>
     * This implementation throws an exception.
     * </p>
     *
     * @param modtime The last modification time.
     * @return true if the time was set.
     * @throws Exception Any Exception thrown is wrapped in FileSystemException.
     */
    protected boolean doSetLastModifiedTime(final long modtime) throws Exception {
        throw new FileSystemException("vfs.provider/set-last-modified-not-supported.error");
    }

    /**
     * Make the file or folder readable.
     * <p>
     * Only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}.
     * </p>
     * <p>
     * This implementation returns false.
     * </p>
     *
     * @param readable True to allow access, false to disallow
     * @param ownerOnly If {@code true}, the permission applies only to the owner; otherwise, it applies to everybody.
     * @return true if the operation succeeded
     * @throws Exception Any Exception thrown is wrapped in FileSystemException.
     * @see #setReadable(boolean, boolean)
     * @since 2.1
     */
    protected boolean doSetReadable(final boolean readable, final boolean ownerOnly) throws Exception {
        return false;
    }

    /**
     * Make the file or folder writeable.
     * <p>
     * Only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}.
     * </p>
     *
     * @param writable True to allow access, false to disallow
     * @param ownerOnly If {@code true}, the permission applies only to the owner; otherwise, it applies to everybody.
     * @return true if the operation succeeded
     * @throws Exception Any Exception thrown is wrapped in FileSystemException.
     * @see #setWritable(boolean, boolean)
     * @since 2.1
     */
    protected boolean doSetWritable(final boolean writable, final boolean ownerOnly) throws Exception {
        return false;
    }

    /**
     * Called when the output stream for this file is closed.
     *
     * @throws Exception if an error occurs.
     */
    protected void endOutput() throws Exception {
        if (getType() == FileType.IMAGINARY) {
            // File was created
            handleCreate(FileType.FILE);
        } else {
            // File has changed
            onChange();
        }
    }

    /**
     * Determines if the file exists.
     *
     * @return true if the file exists, false otherwise,
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public boolean exists() throws FileSystemException {
        return getType() != FileType.IMAGINARY;
    }

    private FileName[] extractNames(final FileObject[] objects) {
        if (objects == null) {
            return null;
        }
        return Arrays.stream(objects).map(FileObject::getName).toArray(FileName[]::new);
    }

    @Override
    protected void finalize() throws Throwable {
        fileSystem.fileObjectDestroyed(this);

        super.finalize();
    }

    /**
     * Finds the set of matching descendants of this file, in depthwise order.
     *
     * @param selector The FileSelector.
     * @return list of files or null if the base file (this object) do not exist
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public FileObject[] findFiles(final FileSelector selector) throws FileSystemException {
        final List<FileObject> list = this.listFiles(selector);
        return list == null ? null : list.toArray(FileObjectUtils.EMPTY_ARRAY);
    }

    /**
     * Traverses the descendants of this file, and builds a list of selected files.
     *
     * @param selector The FileSelector.
     * @param depthwise if true files are added after their descendants, before otherwise.
     * @param selected A List of the located FileObjects.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public void findFiles(final FileSelector selector, final boolean depthwise, final List<FileObject> selected)
            throws FileSystemException {
        try {
            if (exists()) {
                // Traverse starting at this file
                final DefaultFileSelectorInfo info = new DefaultFileSelectorInfo();
                info.setBaseFolder(this);
                info.setDepth(0);
                info.setFile(this);
                traverse(info, selector, depthwise, selected);
            }
        } catch (final Exception e) {
            throw new FileSystemException("vfs.provider/find-files.error", fileName, e);
        }
    }

    /**
     * Returns the file system this file belongs to.
     *
     * @return The FileSystem this file is associated with.
     */
    protected AFS getAbstractFileSystem() {
        return fileSystem;
    }

    /**
     * Returns a child of this file.
     *
     * @param name The name of the child to locate.
     * @return The FileObject for the file or null if the child does not exist.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public FileObject getChild(final String name) throws FileSystemException {
        // TODO - use a hashtable when there are a large number of children
        final FileObject[] children = getChildren();
        for (final FileObject element : children) {
            final FileName child = element.getName();
            final String childBaseName = child.getBaseName();
            // TODO - use a comparator to compare names
            if (childBaseName.equals(name) || UriParser.decode(childBaseName).equals(name)) {
                return resolveFile(child);
            }
        }
        return null;
    }

    /**
     * Returns the children of the file.
     *
     * @return an array of FileObjects, one per child.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public FileObject[] getChildren() throws FileSystemException {
        synchronized (fileSystem) {
            // VFS-210
            if (!fileSystem.hasCapability(Capability.LIST_CHILDREN)) {
                throw new FileNotFolderException(fileName);
            }

            /*
             * VFS-210 if (!getType().hasChildren()) { throw new
             * FileSystemException("vfs.provider/list-children-not-folder.error", name); }
             */
            attach();

            // Use cached info, if present
            if (children != null) {
                return resolveFiles(children);
            }

            // allow the filesystem to return resolved children. e.g. prefill type for webdav
            final FileObject[] childrenObjects;
            try {
                childrenObjects = doListChildrenResolved();
                children = extractNames(childrenObjects);
            } catch (final FileSystemException exc) {
                // VFS-210
                throw exc;
            } catch (final Exception exc) {
                throw new FileSystemException("vfs.provider/list-children.error", exc, fileName);
            }

            if (childrenObjects != null) {
                return childrenObjects;
            }

            // List the children
            final String[] files;
            try {
                files = doListChildren();
            } catch (final FileSystemException exc) {
                // VFS-210
                throw exc;
            } catch (final Exception exc) {
                throw new FileSystemException("vfs.provider/list-children.error", exc, fileName);
            }

            if (files == null) {
                // VFS-210
                // honor the new doListChildren contract
                // return null;
                throw new FileNotFolderException(fileName);
            } else if (files.length == 0) {
                // No children
                children = EMPTY_FILE_ARRAY;
            } else {
                // Create file objects for the children
                final FileName[] cache = new FileName[files.length];
                for (int i = 0; i < files.length; i++) {
                    final String file = "./" + files[i]; // VFS-741: assume scheme prefix is filename only
                    cache[i] = fileSystem.getFileSystemManager().resolveName(fileName, file, NameScope.CHILD);
                }
                // VFS-285: only assign the children file names after all of them have been
                // resolved successfully to prevent an inconsistent internal state
                children = cache;
            }

            return resolveFiles(children);
        }
    }

    /**
     * Returns the file's content.
     *
     * @return the FileContent for this FileObject.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public FileContent getContent() throws FileSystemException {
        synchronized (fileSystem) {
            attach();
            if (content == null) {
                content = doCreateFileContent();
            }
            return content;
        }
    }

    /**
     * Creates the FileContentInfo factory.
     *
     * @return The FileContentInfoFactory.
     */
    protected FileContentInfoFactory getFileContentInfoFactory() {
        return fileSystem.getFileSystemManager().getFileContentInfoFactory();
    }

    /**
     * @return FileOperations interface that provides access to the operations API.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public FileOperations getFileOperations() throws FileSystemException {
        if (operations == null) {
            operations = new DefaultFileOperations(this);
        }

        return operations;
    }

    /**
     * Returns the file system this file belongs to.
     *
     * @return The FileSystem this file is associated with.
     */
    @Override
    public FileSystem getFileSystem() {
        return fileSystem;
    }

    /**
     * Returns an input stream to use to read the content of the file.
     *
     * @return The InputStream to access this file's content.
     * @throws FileSystemException if an error occurs.
     */
    public InputStream getInputStream() throws FileSystemException {
        return getInputStream(DEFAULT_BUFFER_SIZE);
    }

    /**
     * Returns an input stream to use to read the content of the file.
     *
     * @param bufferSize buffer size hint.
     * @return The InputStream to access this file's content.
     * @throws FileSystemException if an error occurs.
     */
    public InputStream getInputStream(final int bufferSize) throws FileSystemException {
        // Get the raw input stream
        try {
            return doGetInputStream(bufferSize);
        } catch (final org.apache.commons.vfs2.FileNotFoundException | FileNotFoundException exc) {
            throw new org.apache.commons.vfs2.FileNotFoundException(fileName, exc);
        } catch (final FileSystemException exc) {
            throw exc;
        } catch (final UnsupportedOperationException exc) {
            // Backward compatibility for subclasses before 2.5.0
            if (DO_GET_INPUT_STREAM_INT.equals(exc.getMessage())) {
                try {
                    // Invoke old API.
                    return doGetInputStream();
                } catch (final Exception e) {
                    if (e instanceof FileSystemException) {
                        throw (FileSystemException) e;
                    }
                    throw new FileSystemException("vfs.provider/read.error", fileName, exc);
                }
            }
            throw exc;
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/read.error", fileName, exc);
        }
    }

    /**
     * Returns the name of the file.
     *
     * @return The FileName, never {@code null}.
     */
    @Override
    public FileName getName() {
        return fileName;
    }

    /**
     * Prepares this file for writing. Makes sure it is either a file, or its parent folder exists. Returns an output
     * stream to use to write the content of the file to.
     *
     * @return An OutputStream where the new contents of the file can be written.
     * @throws FileSystemException if an error occurs.
     */
    public OutputStream getOutputStream() throws FileSystemException {
        return getOutputStream(false);
    }

    /**
     * Prepares this file for writing. Makes sure it is either a file, or its parent folder exists. Returns an output
     * stream to use to write the content of the file to.
     *
     * @param bAppend true when append to the file.
     *            Note: If the underlying file system does not support appending, a FileSystemException is thrown.
     * @return An OutputStream where the new contents of the file can be written.
     * @throws FileSystemException if an error occurs; for example:
     *             bAppend is true, and the underlying FileSystem does not support it
     */
    public OutputStream getOutputStream(final boolean bAppend) throws FileSystemException {
        /*
         * VFS-210 if (getType() != FileType.IMAGINARY && !getType().hasContent()) { throw new
         * FileSystemException("vfs.provider/write-not-file.error", name); } if (!isWriteable()) { throw new
         * FileSystemException("vfs.provider/write-read-only.error", name); }
         */

        if (bAppend && !fileSystem.hasCapability(Capability.APPEND_CONTENT)) {
            throw new FileSystemException("vfs.provider/write-append-not-supported.error", fileName);
        }

        if (getType() == FileType.IMAGINARY) {
            // Does not exist - make sure parent does
            final FileObject parent = getParent();
            if (parent != null) {
                parent.createFolder();
            }
        }

        // Get the raw output stream
        try {
            return doGetOutputStream(bAppend);
        } catch (final RuntimeException re) {
            throw re;
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/write.error", exc, fileName);
        }
    }

    /**
     * Returns the parent of the file.
     *
     * @return the parent FileObject.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public FileObject getParent() throws FileSystemException {
        if (this.compareTo(fileSystem.getRoot()) == 0) // equals is not implemented :-/
        {
            if (fileSystem.getParentLayer() == null) {
                // Root file has no parent
                return null;
            }
            // Return the parent of the parent layer
            return fileSystem.getParentLayer().getParent();
        }

        synchronized (fileSystem) {
            // Locate the parent of this file
            if (parent == null) {
                final FileName name = fileName.getParent();
                if (name == null) {
                    return null;
                }
                parent = fileSystem.resolveFile(name);
            }
            return parent;
        }
    }

    /**
     * Returns the receiver as a URI String for public display, like, without a password.
     *
     * @return A URI String without a password, never {@code null}.
     */
    @Override
    public String getPublicURIString() {
        return fileName.getFriendlyURI();
    }

    /**
     * Returns an input/output stream to use to read and write the content of the file in and random manner.
     *
     * @param mode The RandomAccessMode.
     * @return The RandomAccessContent.
     * @throws FileSystemException if an error occurs.
     */
    public RandomAccessContent getRandomAccessContent(final RandomAccessMode mode) throws FileSystemException {
        /*
         * VFS-210 if (!getType().hasContent()) { throw new FileSystemException("vfs.provider/read-not-file.error",
         * name); }
         */

        if (mode.requestRead()) {
            if (!fileSystem.hasCapability(Capability.RANDOM_ACCESS_READ)) {
                throw new FileSystemException("vfs.provider/random-access-read-not-supported.error");
            }
            if (!isReadable()) {
                throw new FileSystemException("vfs.provider/read-not-readable.error", fileName);
            }
        }

        if (mode.requestWrite()) {
            if (!fileSystem.hasCapability(Capability.RANDOM_ACCESS_WRITE)) {
                throw new FileSystemException("vfs.provider/random-access-write-not-supported.error");
            }
            if (!isWriteable()) {
                throw new FileSystemException("vfs.provider/write-read-only.error", fileName);
            }
        }

        // Get the raw input stream
        try {
            return doGetRandomAccessContent(mode);
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/random-access.error", fileName, exc);
        }
    }

    /**
     * Returns the file's type.
     *
     * @return The FileType.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public FileType getType() throws FileSystemException {
        synchronized (fileSystem) {
            attach();

            // VFS-210: get the type only if requested for
            try {
                if (type == null) {
                    setFileType(doGetType());
                }
                if (type == null) {
                    setFileType(FileType.IMAGINARY);
                }
            } catch (final Exception e) {
                throw new FileSystemException("vfs.provider/get-type.error", e, fileName);
            }

            return type;
        }
    }

    /**
     * Returns a URL representation of the file.
     *
     * @return The URL representation of the file.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public URL getURL() throws FileSystemException {
        try {
            return AccessController.doPrivileged((PrivilegedExceptionAction<URL>) () -> {
                final StringBuilder buf = new StringBuilder();
                final String scheme = UriParser.extractScheme(fileSystem.getContext().getFileSystemManager().getSchemes(), fileName.getURI(), buf);
                return new URL(scheme, "", -1, buf.toString(),
                        new DefaultURLStreamHandler(fileSystem.getContext(), fileSystem.getFileSystemOptions()));
            });
        } catch (final PrivilegedActionException e) {
            throw new FileSystemException("vfs.provider/get-url.error", fileName, e.getException());
        }
    }

    /**
     * Called when this file is changed.
     * <p>
     * This will only happen if you monitor the file using {@link org.apache.commons.vfs2.FileMonitor}.
     * </p>
     *
     * @throws Exception if an error occurs.
     */
    protected void handleChanged() throws Exception {
        // Notify the file system
        fileSystem.fireFileChanged(this);
    }

    /**
     * Called when this file is created. Updates cached info and notifies the parent and file system.
     *
     * @param newType The type of the file.
     * @throws Exception if an error occurs.
     */
    protected void handleCreate(final FileType newType) throws Exception {
        synchronized (fileSystem) {
            if (attached) {
                // Fix up state
                injectType(newType);

                removeChildrenCache();

                // Notify subclass
                onChange();
            }

            // Notify parent that its child list may no longer be valid
            notifyParent(this.getName(), newType);

            // Notify the file system
            fileSystem.fireFileCreated(this);
        }
    }

    /**
     * Called when this file is deleted. Updates cached info and notifies subclasses, parent and file system.
     *
     * @throws Exception if an error occurs.
     */
    protected void handleDelete() throws Exception {
        synchronized (fileSystem) {
            if (attached) {
                // Fix up state
                injectType(FileType.IMAGINARY);
                removeChildrenCache();

                // Notify subclass
                onChange();
            }

            // Notify parent that its child list may no longer be valid
            notifyParent(this.getName(), FileType.IMAGINARY);

            // Notify the file system
            fileSystem.fireFileDeleted(this);
        }
    }

    /**
     * This method is meant to add an object where this object holds a strong reference then. E.g. a archive-file system
     * creates a list of all children and they shouldn't get garbage collected until the container is garbage collected
     *
     * @param strongRef The Object to add.
     */
    // TODO should this be a FileObject?
    public void holdObject(final Object strongRef) {
        if (objects == null) {
            objects = new ArrayList<>(INITIAL_LIST_SIZE);
        }
        objects.add(strongRef);
    }

    protected void injectType(final FileType fileType) {
        setFileType(fileType);
    }

    /**
     * Check if the internal state is "attached".
     *
     * @return true if this is the case
     */
    @Override
    public boolean isAttached() {
        return attached;
    }

    /**
     * Check if the content stream is open.
     *
     * @return true if this is the case
     */
    @Override
    public boolean isContentOpen() {
        if (content == null) {
            return false;
        }

        return content.isOpen();
    }

    /**
     * Determines if this file is executable.
     *
     * @return {@code true} if this file is executable, {@code false} if not.
     * @throws FileSystemException On error determining if this file exists.
     */
    @Override
    public boolean isExecutable() throws FileSystemException {
        try {
            return exists() && doIsExecutable();
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/check-is-executable.error", fileName, exc);
        }
    }

    /**
     * Checks if this file is a regular file by using its file type.
     *
     * @return true if this file is a regular file.
     * @throws FileSystemException if an error occurs.
     * @see #getType()
     * @see FileType#FILE
     */
    @Override
    public boolean isFile() throws FileSystemException {
        // Use equals instead of == to avoid any class loader worries.
        return FileType.FILE.equals(this.getType());
    }

    /**
     * Checks if this file is a folder by using its file type.
     *
     * @return true if this file is a regular file.
     * @throws FileSystemException if an error occurs.
     * @see #getType()
     * @see FileType#FOLDER
     */
    @Override
    public boolean isFolder() throws FileSystemException {
        // Use equals instead of == to avoid any class loader worries.
        return FileType.FOLDER.equals(this.getType());
    }

    /**
     * Determines if this file can be read.
     *
     * @return true if the file is a hidden file, false otherwise.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public boolean isHidden() throws FileSystemException {
        try {
            return exists() && doIsHidden();
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/check-is-hidden.error", fileName, exc);
        }
    }

    /**
     * Determines if this file can be read.
     *
     * @return true if the file can be read, false otherwise.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public boolean isReadable() throws FileSystemException {
        try {
            return exists() && doIsReadable();
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/check-is-readable.error", fileName, exc);
        }
    }

    /**
     * Checks if this fileObject is the same file as {@code destFile} just with a different name. E.g. for case
     * insensitive file systems like windows.
     *
     * @param destFile The file to compare to.
     * @return true if the FileObjects are the same.
     * @throws FileSystemException if an error occurs.
     */
    protected boolean isSameFile(final FileObject destFile) throws FileSystemException {
        attach();
        return doIsSameFile(destFile);
    }

    /**
     * Determines if this file can be read.
     *
     * @return true if the file can be read, false otherwise.
     * @throws FileSystemException if an error occurs.
     * @since 2.4
     */
    @Override
    public boolean isSymbolicLink() throws FileSystemException {
        try {
            return exists() && doIsSymbolicLink();
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/check-is-symbolic-link.error", fileName, exc);
        }
    }

    /**
     * Determines if this file can be written to.
     *
     * @return true if the file can be written to, false otherwise.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public boolean isWriteable() throws FileSystemException {
        try {
            if (exists()) {
                return doIsWriteable();
            }
            final FileObject parent = getParent();
            if (parent != null) {
                return parent.isWriteable();
            }
            return true;
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/check-is-writeable.error", fileName, exc);
        }
    }

    /**
     * Returns an iterator over a set of all FileObject in this file object.
     *
     * @return an Iterator.
     */
    @Override
    public Iterator<FileObject> iterator() {
        try {
            return listFiles(Selectors.SELECT_ALL).iterator();
        } catch (final FileSystemException e) {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Lists the set of matching descendants of this file, in depthwise order.
     *
     * @param selector The FileSelector.
     * @return list of files or null if the base file (this object) do not exist or the {@code selector} is null
     * @throws FileSystemException if an error occurs.
     */
    public List<FileObject> listFiles(final FileSelector selector) throws FileSystemException {
        if (!exists() || selector == null) {
            return null;
        }

        final ArrayList<FileObject> list = new ArrayList<>();
        this.findFiles(selector, true, list);
        return list;
    }

    /**
     * Moves (rename) the file to another one.
     *
     * @param destFile The target FileObject.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public void moveTo(final FileObject destFile) throws FileSystemException {
        if (canRenameTo(destFile)) {
            if (!getParent().isWriteable()) {
                throw new FileSystemException("vfs.provider/rename-parent-read-only.error", getName(),
                        getParent().getName());
            }
        } else if (!isWriteable()) {
            throw new FileSystemException("vfs.provider/rename-read-only.error", getName());
        }

        if (destFile.exists() && !isSameFile(destFile)) {
            destFile.deleteAll();
            // throw new FileSystemException("vfs.provider/rename-dest-exists.error", destFile.getName());
        }

        if (canRenameTo(destFile)) {
            // issue rename on same filesystem
            try {
                attach();
                // remember type to avoid attach
                final FileType srcType = getType();

                doRename(destFile);

                FileObjectUtils.getAbstractFileObject(destFile).handleCreate(srcType);
                destFile.close(); // now the destFile is no longer imaginary. force reattach.

                handleDelete(); // fire delete-events. This file-object (src) is like deleted.
            } catch (final RuntimeException re) {
                throw re;
            } catch (final Exception exc) {
                throw new FileSystemException("vfs.provider/rename.error", exc, getName(), destFile.getName());
            }
        } else {
            // different fs - do the copy/delete stuff

            destFile.copyFrom(this, Selectors.SELECT_SELF);

            if ((destFile.getType().hasContent()
                    && destFile.getFileSystem().hasCapability(Capability.SET_LAST_MODIFIED_FILE)
                    || destFile.getType().hasChildren()
                            && destFile.getFileSystem().hasCapability(Capability.SET_LAST_MODIFIED_FOLDER))
                    && fileSystem.hasCapability(Capability.GET_LAST_MODIFIED)) {
                destFile.getContent().setLastModifiedTime(this.getContent().getLastModifiedTime());
            }

            deleteSelf();
        }

    }

    /**
     * Clled after this file-object closed all its streams.
     */
    protected void notifyAllStreamsClosed() {
        // noop
    }

    /**
     * Notify the parent of a change to its children, when a child is created or deleted.
     *
     * @param childName The name of the child.
     * @param newType The type of the child.
     * @throws Exception if an error occurs.
     */
    private void notifyParent(final FileName childName, final FileType newType) throws Exception {
        if (parent == null) {
            final FileName parentName = fileName.getParent();
            if (parentName != null) {
                // Locate the parent, if it is cached
                parent = fileSystem.getFileFromCache(parentName);
            }
        }

        if (parent != null) {
            FileObjectUtils.getAbstractFileObject(parent).childrenChanged(childName, newType);
        }
    }

    /**
     * Called when the type or content of this file changes.
     * <p>
     * This implementation does nothing.
     * </p>
     *
     * @throws Exception if an error occurs.
     */
    protected void onChange() throws Exception {
        // noop
    }

    /**
     * Called when the children of this file change. Allows subclasses to refresh any cached information about the
     * children of this file.
     * <p>
     * This implementation does nothing.
     * </p>
     *
     * @param child The name of the child that changed.
     * @param newType The type of the file.
     * @throws Exception if an error occurs.
     */
    protected void onChildrenChanged(final FileName child, final FileType newType) throws Exception {
        // noop
    }

    /**
     * This will prepare the fileObject to get resynchronized with the underlying file system if required.
     *
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public void refresh() throws FileSystemException {
        // Detach from the file
        try {
            detach();
        } catch (final Exception e) {
            throw new FileSystemException("vfs.provider/resync.error", fileName, e);
        }
    }

    private void removeChildrenCache() {
        children = null;
    }

    private FileObject resolveFile(final FileName child) throws FileSystemException {
        return fileSystem.resolveFile(child);
    }

    /**
     * Finds a file, relative to this file.
     *
     * @param path The path of the file to locate. Can either be a relative path, which is resolved relative to this
     *            file, or an absolute path, which is resolved relative to the file system that contains this file.
     * @return The FileObject.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public FileObject resolveFile(final String path) throws FileSystemException {
        final FileName otherName = fileSystem.getFileSystemManager().resolveName(fileName, path);
        return fileSystem.resolveFile(otherName);
    }

    /**
     * Returns a child by name.
     *
     * @param name The name of the child to locate.
     * @param scope the NameScope.
     * @return The FileObject for the file or null if the child does not exist.
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public FileObject resolveFile(final String name, final NameScope scope) throws FileSystemException {
        // return fs.resolveFile(this.name.resolveName(name, scope));
        return fileSystem.resolveFile(fileSystem.getFileSystemManager().resolveName(this.fileName, name, scope));
    }

    private FileObject[] resolveFiles(final FileName[] children) throws FileSystemException {
        if (children == null) {
            return null;
        }

        final FileObject[] objects = new FileObject[children.length];
        for (int iterChildren = 0; iterChildren < children.length; iterChildren++) {
            objects[iterChildren] = resolveFile(children[iterChildren]);
        }

        return objects;
    }

    @Override
    public boolean setExecutable(final boolean readable, final boolean ownerOnly) throws FileSystemException {
        try {
            return exists() && doSetExecutable(readable, ownerOnly);
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/set-executable.error", fileName, exc);
        }
    }

    private void setFileType(final FileType type) {
        if (type != null && type != FileType.IMAGINARY) {
            try {
                fileName.setType(type);
            } catch (final FileSystemException e) {
                throw new RuntimeException(e.getMessage());
            }
        }
        this.type = type;
    }

    @Override
    public boolean setReadable(final boolean readable, final boolean ownerOnly) throws FileSystemException {
        try {
            return exists() && doSetReadable(readable, ownerOnly);
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/set-readable.error", fileName, exc);
        }
    }

    // --- OPERATIONS ---

    @Override
    public boolean setWritable(final boolean readable, final boolean ownerOnly) throws FileSystemException {
        try {
            return exists() && doSetWritable(readable, ownerOnly);
        } catch (final Exception exc) {
            throw new FileSystemException("vfs.provider/set-writeable.error", fileName, exc);
        }
    }

    /**
     * Returns the URI as a String.
     *
     * @return Returns the URI as a String.
     */
    @Override
    public String toString() {
        return fileName.getURI();
    }
}
