| // Copyright 2021 The Bazel Authors. All rights reserved. |
| // |
| // Licensed 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 com.google.devtools.build.lib.vfs; |
| |
| import com.google.common.base.Preconditions; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.nio.channels.ReadableByteChannel; |
| import java.nio.channels.SeekableByteChannel; |
| import java.util.Collection; |
| |
| /** |
| * FileSystem implementation which delegates all operations to a provided instance with a |
| * transformed path. |
| * |
| * <p>Please consider using {@link DelegateFileSystem} if you don't need to transform the paths. |
| */ |
| public abstract class PathTransformingDelegateFileSystem extends FileSystem { |
| |
| protected final FileSystem delegateFs; |
| |
| public PathTransformingDelegateFileSystem(FileSystem delegateFs) { |
| super(Preconditions.checkNotNull(delegateFs, "delegateFs").getDigestFunction()); |
| this.delegateFs = delegateFs; |
| } |
| |
| @Override |
| public boolean supportsModifications(PathFragment path) { |
| return delegateFs.supportsModifications(toDelegatePath(path)); |
| } |
| |
| @Override |
| public boolean supportsSymbolicLinksNatively(PathFragment path) { |
| return delegateFs.supportsSymbolicLinksNatively(toDelegatePath(path)); |
| } |
| |
| @Override |
| public boolean supportsHardLinksNatively(PathFragment path) { |
| return delegateFs.supportsHardLinksNatively(toDelegatePath(path)); |
| } |
| |
| @Override |
| public boolean isFilePathCaseSensitive() { |
| return delegateFs.isFilePathCaseSensitive(); |
| } |
| |
| @Override |
| public boolean createDirectory(PathFragment path) throws IOException { |
| return delegateFs.createDirectory(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected boolean createWritableDirectory(PathFragment path) throws IOException { |
| return delegateFs.createWritableDirectory(toDelegatePath(path)); |
| } |
| |
| @Override |
| public void createDirectoryAndParents(PathFragment path) throws IOException { |
| delegateFs.createDirectoryAndParents(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected long getFileSize(PathFragment path, boolean followSymlinks) throws IOException { |
| return delegateFs.getFileSize(toDelegatePath(path), followSymlinks); |
| } |
| |
| @Override |
| protected boolean delete(PathFragment path) throws IOException { |
| return delegateFs.delete(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected long getLastModifiedTime(PathFragment path, boolean followSymlinks) throws IOException { |
| return delegateFs.getLastModifiedTime(toDelegatePath(path), followSymlinks); |
| } |
| |
| @Override |
| public void setLastModifiedTime(PathFragment path, long newTime) throws IOException { |
| delegateFs.setLastModifiedTime(toDelegatePath(path), newTime); |
| } |
| |
| @Override |
| protected boolean isSymbolicLink(PathFragment path) { |
| return delegateFs.isSymbolicLink(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected boolean isDirectory(PathFragment path, boolean followSymlinks) { |
| return delegateFs.isDirectory(toDelegatePath(path), followSymlinks); |
| } |
| |
| @Override |
| protected boolean isFile(PathFragment path, boolean followSymlinks) { |
| return delegateFs.isFile(toDelegatePath(path), followSymlinks); |
| } |
| |
| @Override |
| protected boolean isSpecialFile(PathFragment path, boolean followSymlinks) { |
| return delegateFs.isSpecialFile(toDelegatePath(path), followSymlinks); |
| } |
| |
| @Override |
| protected void createSymbolicLink(PathFragment linkPath, PathFragment targetFragment) |
| throws IOException { |
| delegateFs.createSymbolicLink(toDelegatePath(linkPath), targetFragment); |
| } |
| |
| @Override |
| protected PathFragment readSymbolicLink(PathFragment path) throws IOException { |
| return fromDelegatePath(delegateFs.readSymbolicLink(toDelegatePath(path))); |
| } |
| |
| @Override |
| protected boolean exists(PathFragment path, boolean followSymlinks) { |
| return delegateFs.exists(toDelegatePath(path), followSymlinks); |
| } |
| |
| @Override |
| public boolean exists(PathFragment path) { |
| return delegateFs.exists(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected Collection<String> getDirectoryEntries(PathFragment path) throws IOException { |
| return delegateFs.getDirectoryEntries(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected boolean isReadable(PathFragment path) throws IOException { |
| return delegateFs.isReadable(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected void setReadable(PathFragment path, boolean readable) throws IOException { |
| delegateFs.setReadable(toDelegatePath(path), readable); |
| } |
| |
| @Override |
| protected boolean isWritable(PathFragment path) throws IOException { |
| return delegateFs.isWritable(toDelegatePath(path)); |
| } |
| |
| @Override |
| public void setWritable(PathFragment path, boolean writable) throws IOException { |
| delegateFs.setWritable(toDelegatePath(path), writable); |
| } |
| |
| @Override |
| protected boolean isExecutable(PathFragment path) throws IOException { |
| return delegateFs.isExecutable(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected void setExecutable(PathFragment path, boolean executable) throws IOException { |
| delegateFs.setExecutable(toDelegatePath(path), executable); |
| } |
| |
| @Override |
| protected InputStream getInputStream(PathFragment path) throws IOException { |
| return delegateFs.getInputStream(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected ReadableByteChannel createReadableByteChannel(PathFragment path) throws IOException { |
| return delegateFs.createReadableByteChannel(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected SeekableByteChannel createReadWriteByteChannel(PathFragment path) throws IOException { |
| return delegateFs.createReadWriteByteChannel(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected OutputStream getOutputStream(PathFragment path, boolean append, boolean internal) |
| throws IOException { |
| return delegateFs.getOutputStream(toDelegatePath(path), append, internal); |
| } |
| |
| @Override |
| public void renameTo(PathFragment sourcePath, PathFragment targetPath) throws IOException { |
| delegateFs.renameTo(toDelegatePath(sourcePath), toDelegatePath(targetPath)); |
| } |
| |
| @Override |
| protected void createFSDependentHardLink(PathFragment linkPath, PathFragment originalPath) |
| throws IOException { |
| delegateFs.createFSDependentHardLink(toDelegatePath(linkPath), toDelegatePath(originalPath)); |
| } |
| |
| @Override |
| public String getFileSystemType(PathFragment path) { |
| return delegateFs.getFileSystemType(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected void deleteTree(PathFragment path) throws IOException { |
| delegateFs.deleteTree(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected void deleteTreesBelow(PathFragment dir) throws IOException { |
| delegateFs.deleteTreesBelow(toDelegatePath(dir)); |
| } |
| |
| @Override |
| public byte[] getxattr(PathFragment path, String name, boolean followSymlinks) |
| throws IOException { |
| return delegateFs.getxattr(toDelegatePath(path), name, followSymlinks); |
| } |
| |
| @Override |
| protected byte[] getFastDigest(PathFragment path) throws IOException { |
| return delegateFs.getFastDigest(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected byte[] getDigest(PathFragment path) throws IOException { |
| return delegateFs.getDigest(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected PathFragment resolveOneLink(PathFragment path) throws IOException { |
| return delegateFs.resolveOneLink(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected Path resolveSymbolicLinks(PathFragment path) throws IOException { |
| return getPath( |
| fromDelegatePath(delegateFs.resolveSymbolicLinks(toDelegatePath(path)).asFragment())); |
| } |
| |
| @Override |
| protected FileStatus stat(PathFragment path, boolean followSymlinks) throws IOException { |
| return delegateFs.stat(toDelegatePath(path), followSymlinks); |
| } |
| |
| @Override |
| protected FileStatus statNullable(PathFragment path, boolean followSymlinks) { |
| return delegateFs.statNullable(toDelegatePath(path), followSymlinks); |
| } |
| |
| @Override |
| protected FileStatus statIfFound(PathFragment path, boolean followSymlinks) throws IOException { |
| return delegateFs.statIfFound(toDelegatePath(path), followSymlinks); |
| } |
| |
| @Override |
| protected PathFragment readSymbolicLinkUnchecked(PathFragment path) throws IOException { |
| return delegateFs.readSymbolicLinkUnchecked(toDelegatePath(path)); |
| } |
| |
| @Override |
| protected Collection<Dirent> readdir(PathFragment path, boolean followSymlinks) |
| throws IOException { |
| return delegateFs.readdir(toDelegatePath(path), followSymlinks); |
| } |
| |
| @Override |
| protected void chmod(PathFragment path, int mode) throws IOException { |
| delegateFs.chmod(toDelegatePath(path), mode); |
| } |
| |
| @Override |
| protected void createHardLink(PathFragment linkPath, PathFragment originalPath) |
| throws IOException { |
| delegateFs.createHardLink(toDelegatePath(linkPath), toDelegatePath(originalPath)); |
| } |
| |
| @Override |
| protected void prefetchPackageAsync(PathFragment path, int maxDirs) { |
| delegateFs.prefetchPackageAsync(toDelegatePath(path), maxDirs); |
| } |
| |
| /** Transform original path to a different one to be used with the {@code delegateFs}. */ |
| protected abstract PathFragment toDelegatePath(PathFragment path); |
| |
| /** |
| * Transform a path from one to be used with {@code delegateFs} to original one. |
| * |
| * <p>We expect that for each {@code path}: {@code |
| * fromDelegatePath(toDelegatePath(path)).equals(path)}. |
| */ |
| protected abstract PathFragment fromDelegatePath(PathFragment delegatePath); |
| } |