001package co.codewizards.cloudstore.core.oio; 002 003import static co.codewizards.cloudstore.core.io.StreamUtil.*; 004 005import java.io.FileInputStream; 006import java.io.FileNotFoundException; 007import java.io.FileOutputStream; 008import java.io.FilenameFilter; 009import java.io.IOException; 010import java.io.RandomAccessFile; 011import java.net.URI; 012 013import org.slf4j.Logger; 014import org.slf4j.LoggerFactory; 015 016import co.codewizards.cloudstore.core.io.IInputStream; 017import co.codewizards.cloudstore.core.io.IOutputStream; 018import co.codewizards.cloudstore.core.util.IOUtil; 019 020/** 021 * @author Sebastian Schefczyk 022 * 023 */ 024public class IoFile implements File { 025 private static final long serialVersionUID = 1L; 026 027 private static final Logger logger = LoggerFactory.getLogger(IoFile.class); 028 029 030 protected final java.io.File ioFile; 031 032 protected IoFile(final String pathname) { 033 this.ioFile = new java.io.File(pathname); 034// _debug_assert_NioFile(); 035 } 036 037 protected IoFile(final File parent, final String child) { 038 final java.io.File ioParent = parent.getIoFile(); 039 this.ioFile = new java.io.File(ioParent, child); 040// _debug_assert_NioFile(); 041 } 042 043 protected IoFile(final String parent, final String child) { 044 this.ioFile = new java.io.File(parent, child); 045// _debug_assert_NioFile(); 046 } 047 048 protected IoFile(final URI uri) { 049 this.ioFile = new java.io.File(uri); 050// _debug_assert_NioFile(); 051 } 052 053 protected IoFile(final java.io.File ioFile) { 054 this.ioFile = ioFile; 055// _debug_assert_NioFile(); 056 } 057 058// private final void _debug_assert_NioFile() { 059// if (this.getClass() == IoFile.class) 060// throw new IllegalStateException("This should not be an instance of IoFile! " + ioFile); 061// 062// if (! this.getClass().getSimpleName().equals("NioFile")) 063// throw new IllegalStateException("This should be an instance of NioFile! " + ioFile); 064// } 065 066 067 @Override 068 public File getParentFile() { 069 final java.io.File parentFile = this.ioFile.getParentFile(); 070 return parentFile != null ? new IoFile(parentFile) : null; 071 } 072 073 @Override 074 public String[] list() { 075 return this.ioFile.list(); 076 } 077 078 @Override 079 public String[] list(final FilenameFilter filenameFilter) { 080 return this.ioFile.list(filenameFilter); 081 } 082 083 @Override 084 public File[] listFiles() { 085 final java.io.File[] ioFiles = this.ioFile.listFiles(); 086 return IoFileUtil.convert(ioFiles); 087 } 088 089 @Override 090 public File[] listFiles(final java.io.FileFilter fileFilter) { 091 final java.io.File[] ioFiles = this.ioFile.listFiles(fileFilter); 092 return IoFileUtil.convert(ioFiles); 093 } 094 095 @Override 096 public File[] listFiles(final FileFilter fileFilter) { 097 final java.io.File[] ioFiles = this.ioFile.listFiles(new FileFilterWrapper(fileFilter)); 098 return IoFileUtil.convert(ioFiles); 099 } 100 101 @Override 102 public File[] listFiles(final FilenameFilter fileFilter) { 103 final java.io.File[] ioFiles = this.ioFile.listFiles(fileFilter); 104 return IoFileUtil.convert(ioFiles); 105 } 106 107 @Override 108 public File getAbsoluteFile() { 109 return new IoFile(ioFile.getAbsoluteFile()); 110 } 111 112 @Override 113 public boolean exists() { 114 return ioFile.exists(); 115 } 116 117 @Override 118 public boolean existsNoFollow() { 119 return ioFile.exists(); 120 } 121 @Override 122 public boolean createNewFile() throws IOException { 123 return ioFile.createNewFile(); 124 } 125 126 @Override 127 public boolean canExecute() { 128 return ioFile.canExecute(); 129 } 130 131 @Override 132 public boolean canRead() { 133 return ioFile.canRead(); 134 } 135 136 @Override 137 public boolean canWrite() { 138 return ioFile.canWrite(); 139 } 140 141 @Override 142 public boolean setExecutable(final boolean executable) { 143 return ioFile.setExecutable(executable); 144 } 145 @Override 146 public boolean setExecutable(final boolean executable, final boolean ownerOnly) { 147 return ioFile.setExecutable(executable, ownerOnly); 148 } 149 150 @Override 151 public boolean setReadable(final boolean readable) { 152 return ioFile.setReadable(readable); 153 } 154 @Override 155 public boolean setReadable(final boolean readable, final boolean ownerOnly) { 156 return ioFile.setReadable(readable, ownerOnly); 157 } 158 159 @Override 160 public boolean setWritable(final boolean writable) { 161 return ioFile.setWritable(writable); 162 } 163 @Override 164 public boolean setWritable(final boolean writable, final boolean ownerOnly) { 165 return ioFile.setWritable(writable, ownerOnly); 166 } 167 168 @Override 169 public int compareTo(final File otherFile) { 170 return ioFile.compareTo(otherFile.getIoFile()); 171 } 172 173 @Override 174 public boolean delete() { 175 return ioFile.delete(); 176 } 177 178 @Override 179 public void deleteOnExit() { 180 ioFile.deleteOnExit(); 181 } 182 183 @Override 184 public void deleteRecursively() { 185 IoFileUtil.deleteRecursively(this); 186 } 187 188 @Override 189 public String getAbsolutePath() { 190 return ioFile.getAbsolutePath(); 191 } 192 193 @Override 194 public File getCanonicalFile() throws IOException { 195 return new IoFile(ioFile.getCanonicalFile()); 196 } 197 198 @Override 199 public String getCanonicalPath() throws IOException { 200 return ioFile.getCanonicalPath(); 201 } 202 203 @Override 204 public long getFreeSpace() { 205 return ioFile.getFreeSpace(); 206 } 207 208 @Override 209 public long length() { 210 return ioFile.length(); 211 } 212 213 @Override 214 public boolean isRegularFileNoFollowLinks() { 215 return this.ioFile.isFile(); 216 } 217 218 @Override 219 public boolean isRegularFileFollowLinks() { 220 return this.ioFile.isFile(); 221 } 222 223 @Override 224 public boolean isDirectoryNoFollowSymLinks() { 225 return this.ioFile.isDirectory(); 226 } 227 228 @Override 229 public boolean isDirectoryFollowSymLinks() { 230 return this.ioFile.isDirectory(); 231 } 232 233 @Override 234 public boolean isSymbolicLink() { 235 // currently: no support for symlinks in this implementation 236 return false; 237 } 238 239 @Override 240 public String readSymbolicLinkToPathString() throws IOException { 241 throw new IllegalStateException("Impossible operation within this implementation: check use method 'isSymbolicLink' before!"); 242 } 243 244 @Override 245 public long getLastModifiedNoFollow() { 246 // currently: no support for symlinks in this implementation => cannot do anything about follow/no-follow (that's exactly the reason for the nio-implementation!) 247 return lastModified(); 248 } 249 250 @Override 251 public boolean renameTo(final File dest) { 252 return ioFile.renameTo(dest.getIoFile()); 253 } 254 255 @Override 256 public boolean setLastModified(final long lastModified) { 257 return ioFile.setLastModified(lastModified); 258 } 259 260 @Override 261 public IOutputStream createOutputStream() throws FileNotFoundException { 262 return castStream(new FileOutputStream(ioFile)); 263 } 264 265 @Override 266 public IInputStream createInputStream() throws FileNotFoundException { 267 return castStream(new FileInputStream(ioFile)); 268 } 269 270 @Override 271 public IOutputStream createOutputStream(final boolean append) throws FileNotFoundException { 272 return castStream(new FileOutputStream(ioFile, append)); 273 } 274 275 @Override 276 public String getName() { 277 return ioFile.getName(); 278 } 279 280 @Override 281 public void createSymbolicLink(final String targetPath) throws IOException { 282 throw new IllegalStateException("Impossible operation within this implementation. Check whether symlinks are available here!"); 283 } 284 285 @Override 286 public long lastModified() { 287 final long result = ioFile.lastModified(); 288 return result; 289 } 290 291 @Override 292 public boolean isAbsolute() { 293 return ioFile.isAbsolute(); 294 } 295 296 @Override 297 public String getPath() { 298 return ioFile.getPath(); 299 } 300 301 @Override 302 public boolean mkdir() { 303 return ioFile.mkdir(); 304 } 305 306 @Override 307 public boolean mkdirs() { 308 return ioFile.mkdirs(); 309 } 310 311 @Override 312 public boolean isDirectory() { 313 return ioFile.isDirectory(); 314 } 315 316 @Override 317 public void move(final File toFile) throws IOException { 318 if (toFile.exists()) 319 throw new IOException("toFile file did already exists!"); 320 if (!this.ioFile.exists()) 321 throw new IllegalArgumentException("Source file did not exists!"); 322 if (this.ioFile.getCanonicalPath().equals(toFile.getCanonicalPath())) 323 return; //nothing to do! 324 325 final boolean renameTo = this.ioFile.renameTo(toFile.getIoFile()); 326 // we try to do a simple rename, but this won't be successful between partitions or non-empty directories. 327 if (renameTo) 328 return; 329 330 // 2nd solution: file: copy and delete 331 if (this.ioFile.isFile()) { 332 IOUtil.copyFile(this, toFile); 333 final boolean delete = this.delete(); 334 if (!delete) 335 throw new IllegalStateException("Problem on moving file from '" 336 + this.ioFile.getCanonicalPath() + 337 "' to " + toFile.getIoFile().getCanonicalPath()); 338 } else if (this.ioFile.isDirectory()) { 339 /* If empty, but has failed the simple renameTo(), the destination 340 * is probably on another partition (very unlikely on IOS). 341 */ 342 if (this.ioFile.listFiles().length == 0) { 343 throw new IllegalArgumentException("Should not occure!"); 344 } else { // non-empty directory 345 /* remark: on IOS should be only one partition available to this app. 346 * And a copy/delete operation of a non-empty directory could 347 * last very long; as in Files.move(), this should be prevented. 348 * Best solution would be to rename recursively, because renaming 349 * also only works on same partition. 350 * Assuming there is only on partition, we assume renaming never fails. 351 * Partition-Detection: Its very hard to detect, whether to files are on the same 352 * partition, in a OS independent and without java.nio.Files. 353 * So we just assume one partition because of IOS. */ 354 IoFileUtil.moveRecursively(this, toFile); 355 } 356 } 357 } 358 359 @Override 360 public void copyToCopyAttributes(final File toFile) throws IOException { 361 if (toFile.exists()) 362 throw new IOException("toFile file did already exists!"); 363 if (!this.ioFile.exists()) 364 throw new IllegalArgumentException("Source file did not exists!"); 365 if (this.ioFile.getCanonicalPath().equals(toFile.getCanonicalPath())) 366 return; //nothing to do! 367 368 if (this.ioFile.isFile()) { 369 IOUtil.copyFile(this, toFile); 370 } else { 371 // java.nio.Files.copy is non-recursive, so must this implementation be! 372 final boolean mkdir = toFile.mkdir(); 373 if (!mkdir) 374 throw new IllegalStateException("Problem on moving directory from '" 375 + this.ioFile.getCanonicalPath() + 376 "'! Could not create directory " + toFile.getIoFile().getCanonicalPath()); 377 } 378 } 379 380 @Override 381 public RandomAccessFile createRandomAccessFile(final String mode) throws FileNotFoundException { 382 return new RandomAccessFile(ioFile, mode); 383 } 384 385 @Override 386 public URI toURI() { 387 return ioFile.toURI(); 388 } 389 390 @Override 391 public boolean isFile() { 392 return ioFile.isFile(); 393 } 394 395 @Override 396 public boolean setLastModifiedNoFollow(final long lastModified) { 397 return ioFile.setLastModified(lastModified); 398 } 399 400 @Override 401 public String relativize(final File target) throws IOException { 402// return IOUtil.getRelativePath(this, target); // TODO result is different, should have a look; the first shared folder was appended. 403 return IoFileRelativePathUtil.getRelativePath(this.ioFile, target.getIoFile()); 404 } 405 406 @Override 407 public long getUsableSpace() { 408 return this.ioFile.getUsableSpace(); 409 } 410 411 @Override 412 public java.io.File getIoFile() { 413 return ioFile; 414 } 415 416 @Override 417 public boolean equals(final Object obj) { 418 if ( !(obj instanceof IoFile) ) 419 return false; 420 421 final IoFile ioFile = (IoFile) obj; 422 return this.ioFile.equals(ioFile.ioFile); 423 } 424 425 @Override 426 public int hashCode() { 427 return ioFile.hashCode(); 428 } 429 430 @Override 431 public String toString() { 432 return this.ioFile.toString(); 433 } 434 435 @Override 436 public File createFile(String ... children) { 437 return OioFileFactory.createFile(this, children); 438 } 439 440// private void writeObject(ObjectOutputStream out) throws IOException { 441// if (!ioFile.isAbsolute()) 442// logger.warn("File is not absolute! This may cause w"); 443// 444// out.defaultWriteObject(); 445// } 446// 447// private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 448// 449// } 450 451}