1 /* 2 * Copyright 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package java.io; 18 19 import java.util.ArrayList; 20 21 import com.google.gwt.storage.client.Storage; 22 23 /** LocalStorage based File implementation for GWT. Should probably have used Harmony as a starting point instead of writing this 24 * from scratch. 25 * 26 * @author Stefan Haustein */ 27 public class File { 28 29 public static final File ROOT = new File(""); 30 31 public static final char separatorChar = '/'; 32 33 public static final String separator = "" + separatorChar; 34 35 public static final char pathSeparatorChar = ':'; 36 37 public static final String pathSeparator = "" + pathSeparatorChar; 38 39 public static final Storage LocalStorage = Storage.getLocalStorageIfSupported(); 40 41 File parent; 42 String name; 43 boolean absolute; 44 File(String pathname)45 public File (String pathname) { 46 while (pathname.endsWith(separator) && pathname.length() > 0) { 47 pathname = pathname.substring(0, pathname.length() - 1); 48 } 49 50 int cut = pathname.lastIndexOf(separatorChar); 51 if (cut == -1) { 52 name = pathname; 53 } else if (cut == 0) { 54 name = pathname.substring(cut); 55 parent = name.equals("") ? null : ROOT; 56 } else { 57 name = pathname.substring(cut + 1); 58 parent = new File(pathname.substring(0, cut)); 59 } 60 61 // Compatibility.println("new File ('"+pathname+ "'); canonical name: '" + getCanonicalPath() + "'"); 62 } 63 File(String parent, String child)64 public File (String parent, String child) { 65 this(new File(parent), child); 66 } 67 File(File parent, String child)68 public File (File parent, String child) { 69 this.parent = parent; 70 this.name = child; 71 } 72 73 /* 74 * public File(URI uri) { } 75 */ 76 getName()77 public String getName () { 78 return name; 79 } 80 getParent()81 public String getParent () { 82 return parent == null ? "" : parent.getPath(); 83 } 84 getParentFile()85 public File getParentFile () { 86 return parent; 87 } 88 getPath()89 public String getPath () { 90 return parent == null ? name : (parent.getPath() + separatorChar + name); 91 } 92 isRoot()93 private boolean isRoot () { 94 return name.equals("") && parent == null; 95 } 96 isAbsolute()97 public boolean isAbsolute () { 98 if (isRoot()) { 99 return true; 100 } 101 if (parent == null) { 102 return false; 103 } 104 return parent.isAbsolute(); 105 } 106 getAbsolutePath()107 public String getAbsolutePath () { 108 String path = getAbsoluteFile().getPath(); 109 return path.length() == 0 ? "/" : path; 110 } 111 getAbsoluteFile()112 public File getAbsoluteFile () { 113 if (isAbsolute()) { 114 return this; 115 } 116 if (parent == null) { 117 return new File(ROOT, name); 118 } 119 return new File(parent.getAbsoluteFile(), name); 120 } 121 getCanonicalPath()122 public String getCanonicalPath () { 123 return getCanonicalFile().getAbsolutePath(); 124 } 125 getCanonicalFile()126 public File getCanonicalFile () { 127 File cParent = parent == null ? null : parent.getCanonicalFile(); 128 if (name.equals(".")) { 129 return cParent == null ? ROOT : cParent; 130 } 131 if (cParent != null && cParent.name.equals("")) { 132 cParent = null; 133 } 134 if (name.equals("..")) { 135 if (cParent == null) { 136 return ROOT; 137 } 138 if (cParent.parent == null) { 139 return ROOT; 140 } 141 return cParent.parent; 142 } 143 if (cParent == null && !name.equals("")) { 144 return new File(ROOT, name); 145 } 146 return new File(cParent, name); 147 } 148 149 /* 150 * public URL toURL() throws MalformedURLException { } 151 * 152 * public URI toURI() { } 153 */ 154 canRead()155 public boolean canRead () { 156 return true; 157 } 158 canWrite()159 public boolean canWrite () { 160 return true; 161 } 162 exists()163 public boolean exists () { 164 return LocalStorage.getItem(getCanonicalPath()) != null; 165 } 166 isDirectory()167 public boolean isDirectory () { 168 String s = LocalStorage.getItem(getCanonicalPath()); 169 return s != null && s.startsWith("{"); 170 } 171 isFile()172 public boolean isFile () { 173 String s = LocalStorage.getItem(getCanonicalPath()); 174 return s != null && !s.startsWith("{"); 175 } 176 isHidden()177 public boolean isHidden () { 178 return false; 179 } 180 lastModified()181 public long lastModified () { 182 return 0; 183 } 184 length()185 public long length () { 186 try { 187 if (!exists()) { 188 return 0; 189 } 190 191 RandomAccessFile raf = new RandomAccessFile(this, "r"); 192 long len = raf.length(); 193 raf.close(); 194 return len; 195 } catch (IOException e) { 196 return 0; 197 } 198 } 199 createNewFile()200 public boolean createNewFile () throws IOException { 201 if (exists()) return false; 202 if (!parent.exists()) return false; 203 LocalStorage.setItem(getCanonicalPath(), RandomAccessFile.btoa("")); 204 return true; 205 } 206 delete()207 public boolean delete () { 208 if (!exists()) { 209 return false; 210 } 211 LocalStorage.removeItem(getCanonicalPath()); 212 return true; 213 } 214 deleteOnExit()215 public void deleteOnExit () { 216 throw new RuntimeException("NYI: File.deleteOnExit()"); 217 } 218 list()219 public String[] list () { 220 throw new RuntimeException("NYI: File.list()"); 221 } 222 223 /* 224 * public String[] list(FilenameFilter filter) { return null; } 225 */ 226 listFiles()227 public File[] listFiles () { 228 return listFiles(null); 229 } 230 listFiles(FilenameFilter filter)231 public File[] listFiles (FilenameFilter filter) { 232 ArrayList<File> files = new ArrayList<File>(); 233 String prefix = getCanonicalPath(); 234 if (!prefix.endsWith(separator)) { 235 prefix += separatorChar; 236 } 237 int cut = prefix.length(); 238 int cnt = LocalStorage.getLength(); 239 for (int i = 0; i < cnt; i++) { 240 String key = LocalStorage.key(i); 241 if (key.startsWith(prefix) && key.indexOf(separatorChar, cut) == -1) { 242 String name = key.substring(cut); 243 if (filter == null || filter.accept(this, name)) { 244 files.add(new File(this, name)); 245 } 246 } 247 } 248 return files.toArray(new File[files.size()]); 249 } 250 251 /* 252 * public File[] listFiles(FileFilter filter) { return null; } 253 */ 254 mkdir()255 public boolean mkdir () { 256 if (parent != null && !parent.exists()) { 257 return false; 258 } 259 if (exists()) { 260 return false; 261 } 262 // We may want to make this a JS map 263 LocalStorage.setItem(getCanonicalPath(), "{}"); 264 return true; 265 } 266 mkdirs()267 public boolean mkdirs () { 268 if (parent != null) { 269 parent.mkdirs(); 270 } 271 return mkdir(); 272 } 273 renameTo(File dest)274 public boolean renameTo (File dest) { 275 throw new RuntimeException("renameTo()"); 276 } 277 setLastModified(long time)278 public boolean setLastModified (long time) { 279 return false; 280 } 281 setReadOnly()282 public boolean setReadOnly () { 283 return false; 284 } 285 listRoots()286 public static File[] listRoots () { 287 return new File[] {ROOT}; 288 } 289 createTempFile(String prefix, String suffix, File directory)290 public static File createTempFile (String prefix, String suffix, File directory) throws IOException { 291 throw new RuntimeException("NYI: createTempFile"); 292 } 293 createTempFile(String prefix, String suffix)294 public static File createTempFile (String prefix, String suffix) throws IOException { 295 throw new RuntimeException("NYI: createTempFile"); 296 } 297 compareTo(File pathname)298 public int compareTo (File pathname) { 299 throw new RuntimeException("NYI: File.compareTo()"); 300 } 301 equals(Object obj)302 public boolean equals (Object obj) { 303 if (!(obj instanceof File)) { 304 return false; 305 } 306 return getPath().equals(((File)obj).getPath()); 307 } 308 hashCode()309 public int hashCode () { 310 return parent != null ? parent.hashCode() + name.hashCode() : name.hashCode(); 311 } 312 toString()313 public String toString () { 314 return name; 315 } 316 } 317