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 import static com.google.common.base.Preconditions.checkState; 21 22 import com.google.common.base.MoreObjects; 23 import java.nio.file.FileAlreadyExistsException; 24 import java.nio.file.NoSuchFileException; 25 import java.nio.file.NotDirectoryException; 26 import java.nio.file.NotLinkException; 27 import java.nio.file.Path; 28 import java.util.Objects; 29 import org.checkerframework.checker.nullness.compatqual.NullableDecl; 30 31 /** 32 * Entry in a directory, containing references to the directory itself, the file the entry links to 33 * and the name of the entry. 34 * 35 * <p>May also represent a non-existent entry if the name does not link to any file in the 36 * directory. 37 */ 38 final class DirectoryEntry { 39 40 private final Directory directory; 41 private final Name name; 42 43 @NullableDecl private final File file; 44 45 @NullableDecl DirectoryEntry next; // for use in Directory 46 DirectoryEntry(Directory directory, Name name, @NullableDecl File file)47 DirectoryEntry(Directory directory, Name name, @NullableDecl File file) { 48 this.directory = checkNotNull(directory); 49 this.name = checkNotNull(name); 50 this.file = file; 51 } 52 53 /** Returns {@code true} if and only if this entry represents an existing file. */ exists()54 public boolean exists() { 55 return file != null; 56 } 57 58 /** 59 * Checks that this entry exists, throwing an exception if not. 60 * 61 * @return this 62 * @throws NoSuchFileException if this entry does not exist 63 */ requireExists(Path pathForException)64 public DirectoryEntry requireExists(Path pathForException) throws NoSuchFileException { 65 if (!exists()) { 66 throw new NoSuchFileException(pathForException.toString()); 67 } 68 return this; 69 } 70 71 /** 72 * Checks that this entry does not exist, throwing an exception if it does. 73 * 74 * @return this 75 * @throws FileAlreadyExistsException if this entry does not exist 76 */ requireDoesNotExist(Path pathForException)77 public DirectoryEntry requireDoesNotExist(Path pathForException) 78 throws FileAlreadyExistsException { 79 if (exists()) { 80 throw new FileAlreadyExistsException(pathForException.toString()); 81 } 82 return this; 83 } 84 85 /** 86 * Checks that this entry exists and links to a directory, throwing an exception if not. 87 * 88 * @return this 89 * @throws NoSuchFileException if this entry does not exist 90 * @throws NotDirectoryException if this entry does not link to a directory 91 */ requireDirectory(Path pathForException)92 public DirectoryEntry requireDirectory(Path pathForException) 93 throws NoSuchFileException, NotDirectoryException { 94 requireExists(pathForException); 95 if (!file().isDirectory()) { 96 throw new NotDirectoryException(pathForException.toString()); 97 } 98 return this; 99 } 100 101 /** 102 * Checks that this entry exists and links to a symbolic link, throwing an exception if not. 103 * 104 * @return this 105 * @throws NoSuchFileException if this entry does not exist 106 * @throws NotLinkException if this entry does not link to a symbolic link 107 */ requireSymbolicLink(Path pathForException)108 public DirectoryEntry requireSymbolicLink(Path pathForException) 109 throws NoSuchFileException, NotLinkException { 110 requireExists(pathForException); 111 if (!file().isSymbolicLink()) { 112 throw new NotLinkException(pathForException.toString()); 113 } 114 return this; 115 } 116 117 /** Returns the directory containing this entry. */ directory()118 public Directory directory() { 119 return directory; 120 } 121 122 /** Returns the name of this entry. */ name()123 public Name name() { 124 return name; 125 } 126 127 /** 128 * Returns the file this entry links to. 129 * 130 * @throws IllegalStateException if the file does not exist 131 */ file()132 public File file() { 133 checkState(exists()); 134 return file; 135 } 136 137 /** Returns the file this entry links to or {@code null} if the file does not exist */ 138 @NullableDecl fileOrNull()139 public File fileOrNull() { 140 return file; 141 } 142 143 @Override equals(Object obj)144 public boolean equals(Object obj) { 145 if (obj instanceof DirectoryEntry) { 146 DirectoryEntry other = (DirectoryEntry) obj; 147 return directory.equals(other.directory) 148 && name.equals(other.name) 149 && Objects.equals(file, other.file); 150 } 151 return false; 152 } 153 154 @Override hashCode()155 public int hashCode() { 156 return Objects.hash(directory, name, file); 157 } 158 159 @Override toString()160 public String toString() { 161 return MoreObjects.toStringHelper(this) 162 .add("directory", directory) 163 .add("name", name) 164 .add("file", file) 165 .toString(); 166 } 167 } 168