• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.jimfs;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.base.Supplier;
22 import com.google.common.collect.ImmutableMap;
23 import com.google.common.collect.ImmutableSet;
24 import com.google.common.collect.ImmutableSortedSet;
25 import java.io.IOException;
26 import java.nio.file.FileStore;
27 import java.nio.file.LinkOption;
28 import java.nio.file.NoSuchFileException;
29 import java.nio.file.attribute.BasicFileAttributes;
30 import java.nio.file.attribute.FileAttribute;
31 import java.nio.file.attribute.FileAttributeView;
32 import java.nio.file.attribute.FileStoreAttributeView;
33 import java.util.Set;
34 import java.util.concurrent.locks.Lock;
35 import java.util.concurrent.locks.ReadWriteLock;
36 import java.util.concurrent.locks.ReentrantReadWriteLock;
37 import org.checkerframework.checker.nullness.compatqual.NullableDecl;
38 
39 /**
40  * {@link FileStore} implementation which provides methods for file creation, lookup and attribute
41  * handling.
42  *
43  * <p>Most of these methods are actually implemented in another class: {@link FileTree} for lookup,
44  * {@link FileFactory} for creating and copying files and {@link AttributeService} for attribute
45  * handling. This class merely provides a single API through which to access the functionality of
46  * those classes.
47  *
48  * @author Colin Decker
49  */
50 final class JimfsFileStore extends FileStore {
51 
52   private final FileTree tree;
53   private final HeapDisk disk;
54   private final AttributeService attributes;
55   private final FileFactory factory;
56   private final ImmutableSet<Feature> supportedFeatures;
57   private final FileSystemState state;
58 
59   private final Lock readLock;
60   private final Lock writeLock;
61 
JimfsFileStore( FileTree tree, FileFactory factory, HeapDisk disk, AttributeService attributes, ImmutableSet<Feature> supportedFeatures, FileSystemState state)62   public JimfsFileStore(
63       FileTree tree,
64       FileFactory factory,
65       HeapDisk disk,
66       AttributeService attributes,
67       ImmutableSet<Feature> supportedFeatures,
68       FileSystemState state) {
69     this.tree = checkNotNull(tree);
70     this.factory = checkNotNull(factory);
71     this.disk = checkNotNull(disk);
72     this.attributes = checkNotNull(attributes);
73     this.supportedFeatures = checkNotNull(supportedFeatures);
74     this.state = checkNotNull(state);
75 
76     ReadWriteLock lock = new ReentrantReadWriteLock();
77     this.readLock = lock.readLock();
78     this.writeLock = lock.writeLock();
79   }
80 
81   // internal use methods
82 
83   /** Returns the file system state object. */
state()84   FileSystemState state() {
85     return state;
86   }
87 
88   /** Returns the read lock for this store. */
readLock()89   Lock readLock() {
90     return readLock;
91   }
92 
93   /** Returns the write lock for this store. */
writeLock()94   Lock writeLock() {
95     return writeLock;
96   }
97 
98   /** Returns the names of the root directories in this store. */
getRootDirectoryNames()99   ImmutableSortedSet<Name> getRootDirectoryNames() {
100     state.checkOpen();
101     return tree.getRootDirectoryNames();
102   }
103 
104   /** Returns the root directory with the given name or {@code null} if no such directory exists. */
105   @NullableDecl
getRoot(Name name)106   Directory getRoot(Name name) {
107     DirectoryEntry entry = tree.getRoot(name);
108     return entry == null ? null : (Directory) entry.file();
109   }
110 
111   /** Returns whether or not the given feature is supported by this file store. */
supportsFeature(Feature feature)112   boolean supportsFeature(Feature feature) {
113     return supportedFeatures.contains(feature);
114   }
115 
116   /**
117    * Looks up the file at the given path using the given link options. If the path is relative, the
118    * lookup is relative to the given working directory.
119    *
120    * @throws NoSuchFileException if an element of the path other than the final element does not
121    *     resolve to a directory or symbolic link (e.g. it doesn't exist or is a regular file)
122    * @throws IOException if a symbolic link cycle is detected or the depth of symbolic link
123    *     recursion otherwise exceeds a threshold
124    */
lookUp(File workingDirectory, JimfsPath path, Set<? super LinkOption> options)125   DirectoryEntry lookUp(File workingDirectory, JimfsPath path, Set<? super LinkOption> options)
126       throws IOException {
127     state.checkOpen();
128     return tree.lookUp(workingDirectory, path, options);
129   }
130 
131   /** Returns a supplier that creates a new regular file. */
regularFileCreator()132   Supplier<RegularFile> regularFileCreator() {
133     state.checkOpen();
134     return factory.regularFileCreator();
135   }
136 
137   /** Returns a supplier that creates a new directory. */
directoryCreator()138   Supplier<Directory> directoryCreator() {
139     state.checkOpen();
140     return factory.directoryCreator();
141   }
142 
143   /** Returns a supplier that creates a new symbolic link with the given target. */
symbolicLinkCreator(JimfsPath target)144   Supplier<SymbolicLink> symbolicLinkCreator(JimfsPath target) {
145     state.checkOpen();
146     return factory.symbolicLinkCreator(target);
147   }
148 
149   /**
150    * Creates a copy of the given file, copying its attributes as well according to the given {@code
151    * attributeCopyOption}.
152    */
copyWithoutContent(File file, AttributeCopyOption attributeCopyOption)153   File copyWithoutContent(File file, AttributeCopyOption attributeCopyOption) throws IOException {
154     File copy = factory.copyWithoutContent(file);
155     setInitialAttributes(copy);
156     attributes.copyAttributes(file, copy, attributeCopyOption);
157     return copy;
158   }
159 
160   /**
161    * Sets initial attributes on the given file. Sets default attributes first, then attempts to set
162    * the given user-provided attributes.
163    */
setInitialAttributes(File file, FileAttribute<?>... attrs)164   void setInitialAttributes(File file, FileAttribute<?>... attrs) {
165     state.checkOpen();
166     attributes.setInitialAttributes(file, attrs);
167   }
168 
169   /**
170    * Returns an attribute view of the given type for the given file lookup callback, or {@code null}
171    * if the view type is not supported.
172    */
173   @NullableDecl
getFileAttributeView(FileLookup lookup, Class<V> type)174   <V extends FileAttributeView> V getFileAttributeView(FileLookup lookup, Class<V> type) {
175     state.checkOpen();
176     return attributes.getFileAttributeView(lookup, type);
177   }
178 
179   /**
180    * Returns a map containing the attributes described by the given string mapped to their values.
181    */
readAttributes(File file, String attributes)182   ImmutableMap<String, Object> readAttributes(File file, String attributes) {
183     state.checkOpen();
184     return this.attributes.readAttributes(file, attributes);
185   }
186 
187   /**
188    * Returns attributes of the given file as an object of the given type.
189    *
190    * @throws UnsupportedOperationException if the given attributes type is not supported
191    */
readAttributes(File file, Class<A> type)192   <A extends BasicFileAttributes> A readAttributes(File file, Class<A> type) {
193     state.checkOpen();
194     return attributes.readAttributes(file, type);
195   }
196 
197   /** Sets the given attribute to the given value for the given file. */
setAttribute(File file, String attribute, Object value)198   void setAttribute(File file, String attribute, Object value) {
199     state.checkOpen();
200     // TODO(cgdecker): Change attribute stuff to avoid the sad boolean parameter
201     attributes.setAttribute(file, attribute, value, false);
202   }
203 
204   /** Returns the file attribute views supported by this store. */
supportedFileAttributeViews()205   ImmutableSet<String> supportedFileAttributeViews() {
206     state.checkOpen();
207     return attributes.supportedFileAttributeViews();
208   }
209 
210   // methods implementing the FileStore API
211 
212   @Override
name()213   public String name() {
214     return "jimfs";
215   }
216 
217   @Override
type()218   public String type() {
219     return "jimfs";
220   }
221 
222   @Override
isReadOnly()223   public boolean isReadOnly() {
224     return false;
225   }
226 
227   @Override
getTotalSpace()228   public long getTotalSpace() throws IOException {
229     state.checkOpen();
230     return disk.getTotalSpace();
231   }
232 
233   @Override
getUsableSpace()234   public long getUsableSpace() throws IOException {
235     state.checkOpen();
236     return getUnallocatedSpace();
237   }
238 
239   @Override
getUnallocatedSpace()240   public long getUnallocatedSpace() throws IOException {
241     state.checkOpen();
242     return disk.getUnallocatedSpace();
243   }
244 
245   @Override
supportsFileAttributeView(Class<? extends FileAttributeView> type)246   public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
247     state.checkOpen();
248     return attributes.supportsFileAttributeView(type);
249   }
250 
251   @Override
supportsFileAttributeView(String name)252   public boolean supportsFileAttributeView(String name) {
253     state.checkOpen();
254     return attributes.supportedFileAttributeViews().contains(name);
255   }
256 
257   @Override
getFileStoreAttributeView(Class<V> type)258   public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) {
259     state.checkOpen();
260     return null; // no supported views
261   }
262 
263   @Override
getAttribute(String attribute)264   public Object getAttribute(String attribute) throws IOException {
265     throw new UnsupportedOperationException();
266   }
267 }
268