1 package org.robolectric.res; 2 3 import com.google.common.annotations.VisibleForTesting; 4 import java.io.BufferedInputStream; 5 import java.io.File; 6 import java.io.FileFilter; 7 import java.io.FileInputStream; 8 import java.io.IOException; 9 import java.io.InputStream; 10 import java.util.regex.Pattern; 11 import javax.annotation.Nonnull; 12 import org.robolectric.util.Util; 13 14 public class FileFsFile implements FsFile { 15 @VisibleForTesting 16 static String FILE_SEPARATOR = File.separator; 17 18 private final File file; 19 20 FileFsFile(File file) { 21 this.file = file; 22 } 23 24 FileFsFile(String path) { 25 this.file = new File(path); 26 } 27 28 @Override 29 public boolean exists() { 30 return file.exists(); 31 } 32 33 @Override 34 public boolean isDirectory() { 35 return file.isDirectory(); 36 } 37 38 @Override 39 public boolean isFile() { 40 return file.isFile(); 41 } 42 43 @Override 44 public FsFile[] listFiles() { 45 return asFsFiles(file.listFiles()); 46 } 47 48 @Override 49 public FsFile[] listFiles(final Filter filter) { 50 return asFsFiles(file.listFiles(new FileFilter() { 51 @Override 52 public boolean accept(File pathname) { 53 return filter.accept(new FileFsFile(pathname)); 54 } 55 })); 56 } 57 58 @Override 59 public String[] listFileNames() { 60 File[] files = file.listFiles(); 61 if (files == null) return null; 62 String[] strings = new String[files.length]; 63 for (int i = 0; i < files.length; i++) { 64 strings[i] = files[i].getName(); 65 } 66 return strings; 67 } 68 69 @Override 70 public FsFile getParent() { 71 File parentFile = file.getParentFile(); 72 return parentFile == null ? null : Fs.newFile(parentFile); 73 } 74 75 @Override 76 public String getName() { 77 return file.getName(); 78 } 79 80 @Override 81 public InputStream getInputStream() throws IOException { 82 return new BufferedInputStream(new FileInputStream(file)); 83 } 84 85 @Override 86 public byte[] getBytes() throws IOException { 87 return Util.readBytes(new FileInputStream(file)); 88 } 89 90 @Override 91 public FsFile join(String... pathParts) { 92 File f = file; 93 for (String pathPart : pathParts) { 94 for (String part : pathPart.split(Pattern.quote(FILE_SEPARATOR))) { 95 if (!part.equals(".")) { 96 f = new File(f, part); 97 } 98 } 99 } 100 101 return Fs.newFile(f); 102 } 103 104 public File getFile() { 105 return file; 106 } 107 108 @Override 109 public String toString() { 110 return file.getPath(); 111 } 112 113 @Override 114 public boolean equals(Object o) { 115 if (this == o) return true; 116 if (o == null || getClass() != o.getClass()) return false; 117 118 FileFsFile fsFile = (FileFsFile) o; 119 120 return file.equals(fsFile.file); 121 } 122 123 @Override 124 public int hashCode() { 125 return file.hashCode(); 126 } 127 128 @Override 129 public String getBaseName() { 130 String name = getName(); 131 int dotIndex = name.indexOf("."); 132 return dotIndex >= 0 ? name.substring(0, dotIndex) : name; 133 } 134 135 @Override 136 public String getPath() { 137 return file.getPath(); 138 } 139 140 private FsFile[] asFsFiles(File[] files) { 141 if (files == null) return null; 142 FsFile[] fsFiles = new FsFile[files.length]; 143 for (int i = 0; i < files.length; i++) { 144 fsFiles[i] = Fs.newFile(files[i]); 145 } 146 return fsFiles; 147 } 148 149 /** 150 * Construct an FileFsFile from a series of path components. Path components that are 151 * null or empty string will be ignored. 152 * 153 * @param paths Array of path components. 154 * @return New FileFsFile. 155 */ 156 @Nonnull 157 public static FileFsFile from(String... paths) { 158 File file = null; 159 for (String path : paths) { 160 if (path != null && path.length() > 0) { 161 for (String part : path.split(Pattern.quote(FILE_SEPARATOR))) { 162 if (file != null && part.equals(".")) continue; 163 file = (file == null) 164 ? new File(part) 165 : new File(file, part); 166 } 167 } 168 } 169 return new FileFsFile(file); 170 } 171 } 172