diff options
Diffstat (limited to 'jimfs/src/main/java/com/google/common/jimfs/File.java')
-rw-r--r-- | jimfs/src/main/java/com/google/common/jimfs/File.java | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/jimfs/src/main/java/com/google/common/jimfs/File.java b/jimfs/src/main/java/com/google/common/jimfs/File.java new file mode 100644 index 0000000..ce1cc00 --- /dev/null +++ b/jimfs/src/main/java/com/google/common/jimfs/File.java @@ -0,0 +1,280 @@ +/* + * Copyright 2013 Google Inc. + * + * 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.common.jimfs; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Table; +import java.io.IOException; +import java.util.concurrent.locks.ReadWriteLock; +import org.checkerframework.checker.nullness.compatqual.NullableDecl; + +/** + * A file object, containing both the file's metadata and content. + * + * @author Colin Decker + */ +public abstract class File { + + private final int id; + + private int links; + + private long creationTime; + private long lastAccessTime; + private long lastModifiedTime; + + @NullableDecl // null when only the basic view is used (default) + private Table<String, String, Object> attributes; + + File(int id) { + this.id = id; + + long now = System.currentTimeMillis(); // TODO(cgdecker): Use a Clock + this.creationTime = now; + this.lastAccessTime = now; + this.lastModifiedTime = now; + } + + /** Returns the ID of this file. */ + public int id() { + return id; + } + + /** + * Returns the size, in bytes, of this file's content. Directories and symbolic links have a size + * of 0. + */ + public long size() { + return 0; + } + + /** Returns whether or not this file is a directory. */ + public final boolean isDirectory() { + return this instanceof Directory; + } + + /** Returns whether or not this file is a regular file. */ + public final boolean isRegularFile() { + return this instanceof RegularFile; + } + + /** Returns whether or not this file is a symbolic link. */ + public final boolean isSymbolicLink() { + return this instanceof SymbolicLink; + } + + /** + * Creates a new file of the same type as this file with the given ID. Does not copy the content + * of this file unless the cost of copying the content is minimal. This is because this method is + * called with a hold on the file system's lock. + */ + abstract File copyWithoutContent(int id); + + /** + * Copies the content of this file to the given file. The given file must be the same type of file + * as this file and should have no content. + * + * <p>This method is used for copying the content of a file after copying the file itself. Does + * nothing by default. + */ + void copyContentTo(File file) throws IOException {} + + /** + * Returns the read-write lock for this file's content, or {@code null} if there is no content + * lock. + */ + @NullableDecl + ReadWriteLock contentLock() { + return null; + } + + /** Called when a stream or channel to this file is opened. */ + void opened() {} + + /** + * Called when a stream or channel to this file is closed. If there are no more streams or + * channels open to the file and it has been deleted, its contents may be deleted. + */ + void closed() {} + + /** + * Called when (a single link to) this file is deleted. There may be links remaining. Does nothing + * by default. + */ + void deleted() {} + + /** Returns whether or not this file is a root directory of the file system. */ + final boolean isRootDirectory() { + // only root directories have their parent link pointing to themselves + return isDirectory() && equals(((Directory) this).parent()); + } + + /** Returns the current count of links to this file. */ + public final synchronized int links() { + return links; + } + + /** + * Called when this file has been linked in a directory. The given entry is the new directory + * entry that links to this file. + */ + void linked(DirectoryEntry entry) { + checkNotNull(entry); + } + + /** Called when this file has been unlinked from a directory, either for a move or delete. */ + void unlinked() {} + + /** Increments the link count for this file. */ + final synchronized void incrementLinkCount() { + links++; + } + + /** Decrements the link count for this file. */ + final synchronized void decrementLinkCount() { + links--; + } + + /** Gets the creation time of the file. */ + @SuppressWarnings("GoodTime") // should return a java.time.Instant + public final synchronized long getCreationTime() { + return creationTime; + } + + /** Gets the last access time of the file. */ + @SuppressWarnings("GoodTime") // should return a java.time.Instant + public final synchronized long getLastAccessTime() { + return lastAccessTime; + } + + /** Gets the last modified time of the file. */ + @SuppressWarnings("GoodTime") // should return a java.time.Instant + public final synchronized long getLastModifiedTime() { + return lastModifiedTime; + } + + /** Sets the creation time of the file. */ + final synchronized void setCreationTime(long creationTime) { + this.creationTime = creationTime; + } + + /** Sets the last access time of the file. */ + final synchronized void setLastAccessTime(long lastAccessTime) { + this.lastAccessTime = lastAccessTime; + } + + /** Sets the last modified time of the file. */ + final synchronized void setLastModifiedTime(long lastModifiedTime) { + this.lastModifiedTime = lastModifiedTime; + } + + /** Sets the last access time of the file to the current time. */ + final void updateAccessTime() { + setLastAccessTime(System.currentTimeMillis()); + } + + /** Sets the last modified time of the file to the current time. */ + final void updateModifiedTime() { + setLastModifiedTime(System.currentTimeMillis()); + } + + /** + * Returns the names of the attributes contained in the given attribute view in the file's + * attributes table. + */ + public final synchronized ImmutableSet<String> getAttributeNames(String view) { + if (attributes == null) { + return ImmutableSet.of(); + } + return ImmutableSet.copyOf(attributes.row(view).keySet()); + } + + /** Returns the attribute keys contained in the attributes map for the file. */ + @VisibleForTesting + final synchronized ImmutableSet<String> getAttributeKeys() { + if (attributes == null) { + return ImmutableSet.of(); + } + + ImmutableSet.Builder<String> builder = ImmutableSet.builder(); + for (Table.Cell<String, String, Object> cell : attributes.cellSet()) { + builder.add(cell.getRowKey() + ':' + cell.getColumnKey()); + } + return builder.build(); + } + + /** Gets the value of the given attribute in the given view. */ + @NullableDecl + public final synchronized Object getAttribute(String view, String attribute) { + if (attributes == null) { + return null; + } + return attributes.get(view, attribute); + } + + /** Sets the given attribute in the given view to the given value. */ + public final synchronized void setAttribute(String view, String attribute, Object value) { + if (attributes == null) { + attributes = HashBasedTable.create(); + } + attributes.put(view, attribute, value); + } + + /** Deletes the given attribute from the given view. */ + public final synchronized void deleteAttribute(String view, String attribute) { + if (attributes != null) { + attributes.remove(view, attribute); + } + } + + /** Copies basic attributes (file times) from this file to the given file. */ + final synchronized void copyBasicAttributes(File target) { + target.setFileTimes(creationTime, lastModifiedTime, lastAccessTime); + } + + private synchronized void setFileTimes( + long creationTime, long lastModifiedTime, long lastAccessTime) { + this.creationTime = creationTime; + this.lastModifiedTime = lastModifiedTime; + this.lastAccessTime = lastAccessTime; + } + + /** Copies the attributes from this file to the given file. */ + final synchronized void copyAttributes(File target) { + copyBasicAttributes(target); + target.putAll(attributes); + } + + private synchronized void putAll(@NullableDecl Table<String, String, Object> attributes) { + if (attributes != null && this.attributes != attributes) { + if (this.attributes == null) { + this.attributes = HashBasedTable.create(); + } + this.attributes.putAll(attributes); + } + } + + @Override + public final String toString() { + return MoreObjects.toStringHelper(this).add("id", id()).toString(); + } +} |