diff options
author | Colin Decker <cgdecker@google.com> | 2013-10-09 11:55:25 -0400 |
---|---|---|
committer | Colin Decker <cgdecker@google.com> | 2013-10-09 11:55:25 -0400 |
commit | 7a8cac73d69714f7213c5ef86d90f0ede92e8461 (patch) | |
tree | 27208d21053d1822ec9b8d8d70432488bb0acad3 /jimfs/src/main | |
parent | 7c069a609098d38381252dc40c90167df291d14b (diff) | |
download | jimfs-7a8cac73d69714f7213c5ef86d90f0ede92e8461.tar.gz |
Add the ability to configure whether or not links and/or symbolic links are supported.
Diffstat (limited to 'jimfs/src/main')
5 files changed, 105 insertions, 17 deletions
diff --git a/jimfs/src/main/java/com/google/jimfs/Jimfs.java b/jimfs/src/main/java/com/google/jimfs/Jimfs.java index a179a42..16109b4 100644 --- a/jimfs/src/main/java/com/google/jimfs/Jimfs.java +++ b/jimfs/src/main/java/com/google/jimfs/Jimfs.java @@ -31,6 +31,12 @@ import java.io.IOException; import java.net.URI; import java.nio.file.FileSystem; import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.FileAttribute; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -59,12 +65,19 @@ public final class Jimfs { /** * Returns a new in-memory file system with semantics similar to UNIX. * - * <p>The returned file system has a single root, "/", and uses "/" as a separator. It supports - * symbolic and hard links. File lookup is case-sensitive. Only the "basic" file attribute view - * is supported. The working directory for the file system is "/work". + * <p>The returned file system: + * + * <ul> + * <li>uses "/" as the path name separator (see {@link PathType#unix()} for more information on + * the path format)</li> + * <li>has root "/" and working directory "/work"</li> + * <li>supports symbolic links and hard links</li> + * <li>does case-sensitive lookup</li> + * <li>supports only the "basic" file attribute view</li> + * </ul> * * <p>For more advanced configuration, including changing the working directory, supported - * attribute views or type of storage to use or for setting the host name to be used in the file + * attribute views or supported features or for setting the host name to be used in the file * system's URI, use {@link #newUnixLikeConfiguration()}. */ public static FileSystem newUnixLikeFileSystem() { @@ -74,7 +87,8 @@ public final class Jimfs { /** * Returns a new {@link Configuration} instance with defaults for a UNIX-like file * system. If no changes are made to the configuration, the file system it creates will be - * identical to that created by {@link #newUnixLikeFileSystem()}. + * identical to that created by {@link #newUnixLikeFileSystem()}. Legal paths are described by + * {@link PathType#unix()}. Only one root, "/", is allowed. * * <p>Example usage: * @@ -90,19 +104,27 @@ public final class Jimfs { public static Configuration newUnixLikeConfiguration() { return newConfiguration(PathType.unix()) .addRoots("/") - .setWorkingDirectory("/work"); + .setWorkingDirectory("/work") + .setSupportedFeatures(Feature.LINKS, Feature.SYMBOLIC_LINKS); + } /** * Returns a new in-memory file system with semantics similar to Windows. * - * <p>The returned file system has a single root, "C:\", and uses "\" as a separator. It also - * recognizes "/" as a separator when parsing paths. It supports symbolic and hard links. File - * lookup is not case-sensitive. Only the "basic" file attribute view is supported. The working - * directory for the file system is "C:\work". + * <p>The returned file system: + * + * <ul> + * <li>uses "\" as the path name separator and recognizes "/" as a separator when parsing + * paths (see {@link PathType#windows()} for more information on path format)</li> + * <li>has root "C:\" and working directory "C:\work"</li> + * <li>supports symbolic links but not hard links</li> + * <li>does case-insensitive lookup (for ASCII characters only)</li> + * <li>supports only the "basic" file attribute view</li> + * </ul> * * <p>For more advanced configuration, including changing the working directory, supported - * attribute views or type of storage to use or for setting the host name to be used in the file + * attribute views or supported features or for setting the host name to be used in the file * system's URI, use {@link #newWindowsLikeConfiguration()}. */ public static FileSystem newWindowsLikeFileSystem() { @@ -112,7 +134,8 @@ public final class Jimfs { /** * Returns a new {@link Configuration} instance with defaults for a Windows-like file system. If * no changes are made to the configuration, the file system it creates will be identical to that - * created by {@link #newWindowsLikeFileSystem()}. + * created by {@link #newWindowsLikeFileSystem()}. Legal roots and paths are described by + * {@link PathType#windows()}. * * <p>Example usage: * @@ -130,7 +153,8 @@ public final class Jimfs { public static Configuration newWindowsLikeConfiguration() { return newConfiguration(PathType.windows()) .addRoots("C:\\") - .setWorkingDirectory("C:\\work"); + .setWorkingDirectory("C:\\work") + .setSupportedFeatures(Feature.SYMBOLIC_LINKS); } /** @@ -168,6 +192,7 @@ public final class Jimfs { private String workingDirectory; private AttributeViews attributes = AttributeViews.basic(); + private final Set<Feature> supportedFeatures = new HashSet<>(); private Configuration(PathType pathType) { this.pathType = checkNotNull(pathType); @@ -213,6 +238,13 @@ public final class Jimfs { } /** + * Returns the configured set of optional features the file system should support. + */ + public Set<Feature> getSupportedFeatures() { + return Collections.unmodifiableSet(supportedFeatures); + } + + /** * Sets the name for the created file system, which will be used as the host part of the URI * that identifies the file system. For example, if the name is "foo" the file system's URI * will be "jimfs://foo" and the URI of the path "/bar" on the file system will be @@ -276,10 +308,37 @@ public final class Jimfs { } /** + * Sets the optional features the file system should support. Any supported features that were + * previously set are replaced. + */ + public Configuration setSupportedFeatures(Feature... features) { + supportedFeatures.clear(); + supportedFeatures.addAll(Arrays.asList(features)); + return this; + } + + /** * Creates a new file system using this configuration. */ public FileSystem createFileSystem() { return newFileSystem(URI.create(URI_SCHEME + "://" + getName()), this); } } + + /** + * Optional features that may or may not be supported by a file system. + */ + public static enum Feature { + /** + * Controls whether or not {@linkplain Files#createLink(Path, Path) hard links to regular files} + * are supported. + */ + LINKS, + + /** + * Controls whether or not {@linkplain Files#createSymbolicLink(Path, Path, FileAttribute[]) + * symbolic links} are supported. + */ + SYMBOLIC_LINKS + } } diff --git a/jimfs/src/main/java/com/google/jimfs/internal/FileSystemView.java b/jimfs/src/main/java/com/google/jimfs/internal/FileSystemView.java index c229967..18ef445 100644 --- a/jimfs/src/main/java/com/google/jimfs/internal/FileSystemView.java +++ b/jimfs/src/main/java/com/google/jimfs/internal/FileSystemView.java @@ -25,6 +25,7 @@ import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Lists; +import com.google.jimfs.Jimfs; import com.google.jimfs.common.IoSupplier; import java.io.IOException; @@ -282,6 +283,7 @@ final class FileSystemView { */ public File createSymbolicLink( JimfsPath path, JimfsPath target, FileAttribute<?>... attrs) throws IOException { + store.checkSupported(Jimfs.Feature.SYMBOLIC_LINKS); return createFile(path, store.createSymbolicLink(target), false, attrs); } @@ -421,6 +423,8 @@ final class FileSystemView { checkNotNull(existingView); checkNotNull(existing); + store.checkSupported(Jimfs.Feature.LINKS); + if (!isSameFileSystem(existingView)) { throw new FileSystemException(link.toString(), existing.toString(), "can't link: source and target are in different file system instances"); diff --git a/jimfs/src/main/java/com/google/jimfs/internal/JimfsFileStore.java b/jimfs/src/main/java/com/google/jimfs/internal/JimfsFileStore.java index d283391..e28f185 100644 --- a/jimfs/src/main/java/com/google/jimfs/internal/JimfsFileStore.java +++ b/jimfs/src/main/java/com/google/jimfs/internal/JimfsFileStore.java @@ -22,6 +22,7 @@ import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; +import com.google.jimfs.Jimfs; import com.google.jimfs.attribute.AttributeStore; import com.google.jimfs.common.IoSupplier; @@ -32,6 +33,7 @@ import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.FileAttributeView; import java.nio.file.attribute.FileStoreAttributeView; +import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -56,15 +58,18 @@ final class JimfsFileStore extends FileStore { private final AttributeService attributes; private final FileFactory factory; + private final ImmutableSet<Jimfs.Feature> supportedFeatures; + private final Lock readLock; private final Lock writeLock; - public JimfsFileStore( - FileTree tree, FileFactory factory, RegularFileStorage storage, AttributeService attributes) { + public JimfsFileStore(FileTree tree, FileFactory factory, RegularFileStorage storage, + AttributeService attributes, Set<Jimfs.Feature> supportedFeatures) { this.tree = checkNotNull(tree); this.factory = checkNotNull(factory); this.storage = checkNotNull(storage); this.attributes = checkNotNull(attributes); + this.supportedFeatures = ImmutableSet.copyOf(supportedFeatures); ReadWriteLock lock = new ReentrantReadWriteLock(); this.readLock = lock.readLock(); @@ -95,6 +100,24 @@ final class JimfsFileStore extends FileStore { } /** + * Returns whether or not the given feature is supported. + */ + boolean supports(Jimfs.Feature feature) { + return supportedFeatures.contains(feature); + } + + /** + * Checks that the given feature is supported. + * + * @throws UnsupportedOperationException if the feature is not supported + */ + void checkSupported(Jimfs.Feature feature) { + if (!supports(feature)) { + throw new UnsupportedOperationException(); + } + } + + /** * Returns the root directory with the given name or {@code null} if no such directory exists. */ @Nullable diff --git a/jimfs/src/main/java/com/google/jimfs/internal/JimfsFileSystems.java b/jimfs/src/main/java/com/google/jimfs/internal/JimfsFileSystems.java index f0fea63..2fa13a0 100644 --- a/jimfs/src/main/java/com/google/jimfs/internal/JimfsFileSystems.java +++ b/jimfs/src/main/java/com/google/jimfs/internal/JimfsFileSystems.java @@ -72,7 +72,8 @@ final class JimfsFileSystems { rootDir.asDirectoryTable().setRoot(); } - return new JimfsFileStore(new FileTree(superRoot), fileFactory, storage, attributeService); + return new JimfsFileStore(new FileTree(superRoot), fileFactory, storage, + attributeService, config.getSupportedFeatures()); } /** diff --git a/jimfs/src/main/java/com/google/jimfs/path/PathType.java b/jimfs/src/main/java/com/google/jimfs/path/PathType.java index 57bab32..5e51cea 100644 --- a/jimfs/src/main/java/com/google/jimfs/path/PathType.java +++ b/jimfs/src/main/java/com/google/jimfs/path/PathType.java @@ -39,7 +39,8 @@ public abstract class PathType { /** * Returns a Unix-style path type. "/" is both the root and the only separator. Any path starting - * with "/" is considered absolute. Paths are case sensitive. + * with "/" is considered absolute. Paths are case sensitive. The nul character ('\0') is + * disallowed in paths. */ public static PathType unix() { return UnixPathType.INSTANCE; |