/*
 * 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.

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')

Type parameters:
  • <AFS> – An AbstractFileSystem subclass
/** * 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 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.
/** * 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.
/** * FileServices instance. */
private FileOperations operations;
Params:
  • name – the file name - muse be an instance of AbstractFileName
  • fileSystem – the file system
Throws:
/** * * @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.
/** * 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 newfile is possible.
Params:
  • newfile – the new file name
Returns:true if rename is possible
/** * 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.
Params:
  • childName – The name of the child.
  • newType – The type of the child.
Throws:
/** * 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 = new FileName[list.size()]; list.toArray(children); } // removeChildrenCache(); onChildrenChanged(childName, newType); }
Closes this file, and its content.
Throws:
  • FileSystemException – if an error occurs.
/** * 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).
Params:
  • file – the object to compare.
Returns:a negative integer, zero, or a positive integer when this object is less than, equal to, or greater than the given object.
/** * 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.
Params:
  • file – The FileObject to copy.
  • selector – The FileSelector.
Throws:
/** * 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.
/** * 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.
/** * 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.

TODO - This will not fail if this is a non-empty folder.

Throws:
Returns:true if this object has been deleted
/** * 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 selector.
Params:
  • selector – The FileSelector.
Throws:
Returns:the number of deleted files.
/** * 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 (int i = 0; i < count; i++) { final AbstractFileObject file = FileObjectUtils.getAbstractFileObject(files.get(i)); // 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 delete(Selectors.SELECT_ALL)
Throws:
See Also:
Returns:the number of deleted files.
/** * 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
Throws:
Returns:true if this file has been deleted
/** * 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 doAttach next time this file is used.
Throws:
/** * 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.

This method is called before any of the doBlah() or onBlah() methods. Sub-classes can use this method to perform lazy initialization.

This implementation does nothing.

Throws:
  • Exception – if an error occurs.
/** * 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.
Throws:
Returns:The FileContent.
Since:2.0
/** * 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: This implementation throws an exception.
Throws:
/** * 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: This implementation throws an exception.
Throws:
/** * 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.

Called when this file is closed. Note that the file object may be reused later, so should be able to be reattached.

This implementation does nothing.

Throws:
  • Exception – if an error occurs.
/** * 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 doGetType does not return FileType.IMAGINARY.

This implementation always returns an empty map.

Throws:
Returns:The attributes of the file.
/** * 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 doGetType does not return FileType.IMAGINARY.

This implementation always returns null.

Throws:
Returns:The certificates used to sign the file.
/** * 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 doGetType returns FileType.FILE.
Throws:
Returns:The size of the file in bytes.
/** * 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 doGetType returns FileType.FILE.

It is guaranteed that there are no open output streams for this file when this method is called.

The returned stream does not have to be buffered.

Throws:
Returns:An InputStream to read the file content.
/** * 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 doGetType returns FileType.FILE.

It is guaranteed that there are no open output streams for this file when this method is called.

The returned stream does not have to be buffered.

Params:
  • bufferSize – Buffer size hint.
Throws:
Returns:An InputStream to read the file content.
/** * 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 doGetType does not return

This implementation throws an exception.

Throws:
Returns:The last modification time.
/** * 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: It is guaranteed that there are no open stream (input or output) for this file when this method is called.

The returned stream does not have to be buffered.

This implementation throws an exception.

Params:
  • bAppend – true if the file should be appended to, false if it should be overwritten.
Throws:
Returns:An OutputStream to write to the file.
/** * 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 doGetType returns FileType.FILE.

It is guaranteed that there are no open output streams for this file when this method is called.

Params:
  • mode – The mode to access the file.
Throws:
Returns:The RandomAccessContext.
/** * 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.
Throws:
Returns:the type of the file.
/** * 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 doGetType does not return FileType.IMAGINARY.

This implementation always returns false.

Throws:
Returns:true if the file is executable, false otherwise.
/** * 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 doGetType does not return FileType.IMAGINARY.

This implementation always returns false.

Throws:
Returns:true if the file is hidden, false otherwise.
/** * 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 doGetType does not return FileType.IMAGINARY.

This implementation always returns true.

Throws:
Returns:true if the file is readable, false otherwise.
/** * 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 destFile just with a different name. E.g. for case insensitive file systems like windows.
Params:
  • destFile – The file to compare to.
Throws:
Returns:true if the FileObjects are the same.
/** * 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 doGetType does not return FileType.IMAGINARY.

This implementation always returns false.

Throws:
Returns:true if the file is readable, false otherwise.
Since:2.4
/** * 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 doGetType does not return FileType.IMAGINARY.

This implementation always returns true.

Throws:
Returns:true if the file is writable.
/** * 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 doGetType returns FileType.FOLDER. The return value of this method is cached, so the implementation can be expensive.
Throws:
Returns: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.
/** * 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.

Is only called if doGetType returns FileType.FOLDER.

The return value of this method is cached, so the implementation can be expensive. Other than doListChildren you could return FileObject's to e.g. reinitialize the type of the file.

(Introduced for Webdav: "permission denied on resource" during getType())

Throws:
Returns:The children of this FileObject.
/** * 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.

Is only called if doGetType does not return FileType.IMAGINARY.

This implementation throws an exception.

Params:
  • attrName – The name of the attribute to remove.
Throws:
Since:2.0
/** * 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.

Is only called when:

This implementation throws an exception.

Params:
  • newFile – A FileObject with the new file name.
Throws:
/** * 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.

Is only called if doGetType does not return FileType.IMAGINARY.

This implementation throws an exception.

Params:
  • attrName – The attribute name.
  • value – The value to be associated with the attribute name.
Throws:
/** * 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.

Only called if doGetType does not return FileType.IMAGINARY.

This implementation returns false.

Params:
  • executable – True to allow access, false to disallow.
  • ownerOnly – If true, the permission applies only to the owner; otherwise, it applies to everybody.
Throws:
  • Exception – Any Exception thrown is wrapped in FileSystemException.
See Also:
Returns:true if the operation succeeded.
Since:2.1
/** * 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.

Is only called if doGetType does not return FileType.IMAGINARY.

This implementation throws an exception.

Params:
  • modtime – The last modification time.
Throws:
  • Exception – Any Exception thrown is wrapped in FileSystemException.
Returns:true if the time was set.
/** * 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.

Only called if doGetType does not return FileType.IMAGINARY.

This implementation returns false.

Params:
  • readable – True to allow access, false to disallow
  • ownerOnly – If true, the permission applies only to the owner; otherwise, it applies to everybody.
Throws:
  • Exception – Any Exception thrown is wrapped in FileSystemException.
See Also:
Returns:true if the operation succeeded
Since:2.1
/** * 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.

Only called if doGetType does not return FileType.IMAGINARY.

Params:
  • writable – True to allow access, false to disallow
  • ownerOnly – If true, the permission applies only to the owner; otherwise, it applies to everybody.
Throws:
  • Exception – Any Exception thrown is wrapped in FileSystemException.
See Also:
Returns:true if the operation succeeded
Since:2.1
/** * 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.
/** * 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.
Throws:
Returns:true if the file exists, false otherwise,
/** * 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.
Params:
  • selector – The FileSelector.
Throws:
Returns:list of files or null if the base file (this object) do not exist
/** * 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(new FileObject[list.size()]); }
Traverses the descendants of this file, and builds a list of selected files.
Params:
  • selector – The FileSelector.
  • depthwise – if true files are added after their descendants, before otherwise.
  • selected – A List of the located FileObjects.
Throws:
/** * 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.
Returns:The FileSystem this file is associated with.
/** * 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.
Params:
  • name – The name of the child to locate.
Throws:
Returns:The FileObject for the file or null if the child does not exist.
/** * 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.
Throws:
Returns:an array of FileObjects, one per child.
/** * 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 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.
Throws:
Returns:the FileContent for this FileObject.
/** * 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.
Returns:The FileContentInfoFactory.
/** * Creates the FileContentInfo factory. * * @return The FileContentInfoFactory. */
protected FileContentInfoFactory getFileContentInfoFactory() { return fileSystem.getFileSystemManager().getFileContentInfoFactory(); }
Throws:
Returns:FileOperations interface that provides access to the operations API.
/** * @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.
Returns:The FileSystem this file is associated with.
/** * 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.
Throws:
Returns:The InputStream to access this file's content.
/** * 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.
Params:
  • bufferSize – buffer size hint.
Throws:
Returns:The InputStream to access this file's content.
/** * 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 exc) { throw new org.apache.commons.vfs2.FileNotFoundException(fileName, exc); } catch (final 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.
Returns:The FileName, never null.
/** * 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.
Throws:
Returns:An OutputStream where the new contents of the file can be written.
/** * 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.
Params:
  • bAppend – true when append to the file. Note: If the underlying file system does not support appending, a FileSystemException is thrown.
Throws:
  • FileSystemException – if an error occurs; for example: bAppend is true, and the underlying FileSystem does not support it
Returns:An OutputStream where the new contents of the file can be written.
/** * 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.
Throws:
Returns:the parent FileObject.
/** * 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.
Returns:A URI String without a password, never null.
/** * 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.
Params:
  • mode – The RandomAccessMode.
Throws:
Returns:The RandomAccessContent.
/** * 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.
Throws:
Returns:The FileType.
/** * 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.
Throws:
Returns:The URL representation of the file.
/** * 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.

This will only happen if you monitor the file using FileMonitor.

Throws:
/** * 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.
Params:
  • newType – The type of the file.
Throws:
/** * 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.
/** * 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
Params:
  • strongRef – The Object to add.
/** * 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".
Returns:true if this is the case
/** * 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.
Returns:true if this is the case
/** * 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.
Throws:
Returns:true if this file is executable, false if not.
/** * 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() : false; } 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.
Throws:
See Also:
Returns:true if this file is a regular file.
/** * 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.
Throws:
See Also:
Returns:true if this file is a regular file.
/** * 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.
Throws:
Returns:true if the file is a hidden file, false otherwise.
/** * 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() : false; } catch (final Exception exc) { throw new FileSystemException("vfs.provider/check-is-hidden.error", fileName, exc); } }
Determines if this file can be read.
Throws:
Returns:true if the file can be read, false otherwise.
/** * 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() : false; } catch (final Exception exc) { throw new FileSystemException("vfs.provider/check-is-readable.error", fileName, exc); } }
Checks if this fileObject is the same file as destFile just with a different name. E.g. for case insensitive file systems like windows.
Params:
  • destFile – The file to compare to.
Throws:
Returns:true if the FileObjects are the same.
/** * 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.
Throws:
Returns:true if the file can be read, false otherwise.
Since:2.4
/** * 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() : false; } catch (final Exception exc) { throw new FileSystemException("vfs.provider/check-is-symbolic-link.error", fileName, exc); } }
Determines if this file can be written to.
Throws:
Returns:true if the file can be written to, false otherwise.
/** * 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.
Returns:an Iterator.
/** * 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.
Params:
  • selector – The FileSelector.
Throws:
Returns:list of files or null if the base file (this object) do not exist or the selector is null
/** * 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.
Params:
  • destFile – The target FileObject.
Throws:
/** * 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.
/** * 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.
Params:
  • childName – The name of the child.
  • newType – The type of the child.
Throws:
/** * 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.

This implementation does nothing.

Throws:
  • Exception – if an error occurs.
/** * 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.

This implementation does nothing.

Params:
  • child – The name of the child that changed.
  • newType – The type of the file.
Throws:
/** * 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.
/** * 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.
Params:
  • 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.
Throws:
Returns:The FileObject.
/** * 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.
Params:
  • name – The name of the child to locate.
  • scope – the NameScope.
Throws:
Returns:The FileObject for the file or null if the child does not exist.
/** * 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) : false; } 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) : false; } 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) : false; } catch (final Exception exc) { throw new FileSystemException("vfs.provider/set-writeable.error", fileName, exc); } }
Returns the URI as a String.
Returns:Returns the URI as a String.
/** * Returns the URI as a String. * * @return Returns the URI as a String. */
@Override public String toString() { return fileName.getURI(); } }