aboutsummaryrefslogtreecommitdiff
path: root/jimfs/src/main/java/com/google/common/jimfs/File.java
diff options
context:
space:
mode:
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.java280
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();
+ }
+}