/src/mpv5/utils/files/FileDirectoryHandler.java
Java | 668 lines | 423 code | 49 blank | 196 comment | 78 complexity | 00917de7f877ced3ec7baa3f2d268289 MD5 | raw file
1/* 2 * 3 * 4 */ 5package mpv5.utils.files; 6 7/** 8 * 9 * Galileo Computing 10 */ 11import java.awt.Desktop; 12import java.io.BufferedOutputStream; 13import java.io.FileNotFoundException; 14 15import java.io.File; 16import java.io.FileInputStream; 17import java.io.FileOutputStream; 18import java.io.IOException; 19import java.io.InputStream; 20import java.io.OutputStream; 21import java.net.URI; 22import java.net.URL; 23import java.net.URLConnection; 24import java.util.ArrayList; 25import java.util.Arrays; 26import java.util.List; 27import java.util.logging.Level; 28import java.util.logging.Logger; 29import mpv5.globals.Constants; 30import mpv5.globals.LocalSettings; 31import mpv5.globals.Messages; 32import mpv5.logging.Log; 33import mpv5.ui.dialogs.DialogForFile; 34import mpv5.ui.dialogs.Notificator; 35import mpv5.ui.dialogs.Popup; 36import mpv5.utils.text.RandomText; 37 38public abstract class FileDirectoryHandler { 39 40 /** 41 * Deletes a file now or later 42 * @param localFile 43 * @param now 44 */ 45 public static void deleteFile(File localFile, boolean now) { 46 if (now) { 47 try { 48 deleteTree(localFile); 49 } catch (IOException ex) { 50 Log.Debug(ex); 51 } 52 } else { 53 localFile.deleteOnExit(); 54 } 55 } 56 57 /** 58 * Deletes a whole directory tree and files in it 59 * @param path 60 * @throws java.io.IOException 61 */ 62 public synchronized static void deleteTree(File path) throws IOException { 63 deleteDirectoryContent(path); 64 if (!path.delete()) { 65 path.deleteOnExit(); 66 } 67 } 68 69 /** 70 * Deletes the content of a directory 71 * @param path 72 * @throws java.io.IOException 73 */ 74 public synchronized static void deleteDirectoryContent(File path) throws IOException { 75 for (File file : path.listFiles()) { 76 if (file.isDirectory()) { 77 deleteTree(file); 78 } else { 79 Log.Debug(FileDirectoryHandler.class, "Delete: " + file.getCanonicalPath()); 80 if (!file.delete()) { 81 file.deleteOnExit(); 82 } 83 } 84 } 85 } 86 87 /** 88 * 89 * @param sourceLocation 90 * @param targetLocation 91 * @return 92 * @throws java.io.IOException 93 */ 94 public static URI copyDirectory(File sourceLocation, File targetLocation) throws IOException { 95 96 if (sourceLocation.isDirectory()) { 97 if (!targetLocation.exists()) { 98 targetLocation.mkdir(); 99 } 100 101 String[] children = sourceLocation.list(); 102 for (int i = 0; i < children.length; i++) { 103 copyDirectory(new File(sourceLocation, children[i]), 104 new File(targetLocation, children[i])); 105 } 106 } else { 107 108 InputStream in = new FileInputStream(sourceLocation); 109 OutputStream out = new FileOutputStream(targetLocation); 110 111 // Copy the bits from instream to outstream 112 byte[] buf = new byte[1024]; 113 int len; 114 while ((len = in.read(buf)) > 0) { 115 out.write(buf, 0, len); 116 } 117 in.close(); 118 out.close(); 119 } 120 return targetLocation.toURI(); 121 } 122 123 /** 124 * Copies a file via stream 125 * @param source 126 * @param target 127 * @return 128 * @throws java.io.FileNotFoundException 129 * @throws java.io.IOException 130 */ 131 public static File copyFile2(File source, File target, boolean silent) throws FileNotFoundException, IOException { 132 Log.Debug(FileDirectoryHandler.class, "Copying file from " 133 + source + " to " + target); 134 return new File(copyFile(source, target, silent)); 135 } 136 137 /** 138 * Copies a file via stream 139 * @param source 140 * @param target 141 * @return 142 * @throws java.io.FileNotFoundException 143 * @throws java.io.IOException 144 */ 145 public static File copyFile2(File source, File target) throws FileNotFoundException, IOException { 146 Log.Debug(FileDirectoryHandler.class, "Copying file from " 147 + source + " to " + target); 148 return new File(copyFile(source, target, true)); 149 } 150 151 /** 152 * Copies a file via stream 153 * @param sourceFile 154 * @param targetDirectory 155 * @param targetFilename 156 * @param deleteOnExit Shall we delete the NEW file on exit 157 * @return 158 * @throws java.io.IOException 159 */ 160 public static URI copyFile(File sourceFile, File targetDirectory, String targetFilename, boolean deleteOnExit) 161 throws IOException { 162 targetFilename = check(targetFilename); 163 return copyFile(sourceFile, targetDirectory, targetFilename, deleteOnExit, true); 164 } 165 166 /** 167 * Copies a file via stream 168 * @param sourceFile 169 * @param targetDirectory 170 * @param targetFilename 171 * @param deleteOnExit Shall we delete the NEW file on exit 172 * @param silent 173 * @return 174 * @throws java.io.IOException 175 */ 176 public static URI copyFile(File sourceFile, File targetDirectory, String targetFilename, boolean deleteOnExit, boolean silent) 177 throws IOException { 178 targetFilename = check(targetFilename); 179 FileOutputStream out = null; 180 InputStream in = new FileInputStream(sourceFile); 181 File outp = null; 182 if (targetDirectory != null) { 183 outp = new File(targetDirectory + File.separator + targetFilename); 184 if (!targetDirectory.exists()) { 185 targetDirectory.mkdirs(); 186 } 187 outp.delete(); 188 out = new FileOutputStream(targetDirectory + File.separator + targetFilename); 189 } else { 190 outp = new File(targetFilename); 191 outp.delete(); 192 out = new FileOutputStream(targetFilename); 193 } 194 195 196 // Copy the bits from instream to outstream 197 byte[] buf = new byte[1024]; 198 int len; 199 while ((len = in.read(buf)) > 0) { 200 out.write(buf, 0, len); 201 } 202 in.close(); 203 out.close(); 204 205 if (deleteOnExit) { 206 outp.deleteOnExit(); 207 } 208 209 if (!silent) { 210 Notificator.raiseNotification(Messages.FILE_SAVED + " " + outp.getPath(), false); 211 } 212 213 return outp.toURI(); 214 } 215 216 /** 217 * Requests that the file or directory denoted by this abstract pathname be deleted when the virtual machine terminates. 218 * Files (or directories) are deleted in the reverse order that they are registered. 219 * Invoking this method to delete a file or directory that is already registered for deletion has no effect. 220 * Deletion will be attempted only for normal termination of the virtual machine, as defined by the Java Language Specification. 221 * Once deletion has been requested, it is not possible to cancel the request. 222 * @param path 223 * @throws IOException 224 */ 225 public static void deleteTreeOnExit(File path) throws IOException { 226 for (File file : path.listFiles()) { 227 if (file.isDirectory()) { 228 deleteTreeOnExit(file); 229 } else { 230 Log.Debug(FileDirectoryHandler.class, "Delete On Exit: " + file.getCanonicalPath()); 231 file.deleteOnExit(); 232 } 233 } 234 path.deleteOnExit(); 235 } 236 237 /** 238 * 239 * @param directory 240 * @param identifier 241 * @return A File array with the files (not directories) within the given directory 242 */ 243 @SuppressWarnings("unchecked") 244 public static File[] getFilesOfDirectory(File directory) { 245 File src; 246 ArrayList<File> lstFiles = new ArrayList<File>(); 247 if (directory.isDirectory()) { 248 try { 249 src = directory; 250 Log.Debug(FileDirectoryHandler.class, "Verzeichnis: " + src); 251 File[] files = src.listFiles(); 252 Log.Debug(FileDirectoryHandler.class, "Dateien analysieren..."); 253 lstFiles = new ArrayList<java.io.File>(); 254 if (files != null && files.length > 0) { 255 for (int i = 0, k = 0; i < files.length; i++) { 256// Log.Debug(this,"Datei analysieren: " + files[i].getName()); 257 if (files[i].isFile()) { 258 try { 259 lstFiles.add(files[i]); 260 Log.Debug(FileDirectoryHandler.class, "Datei gefunden: " + files[i].getName()); 261 k++; 262 } catch (Exception ex) { 263 Log.Debug(FileDirectoryHandler.class, ex.getMessage()); 264 } 265 } 266 } 267 } else { 268 Log.Debug(FileDirectoryHandler.class, "Keine Datei gefunden."); 269 } 270 } catch (Exception exception) { 271 Log.Debug(FileDirectoryHandler.class, exception); 272 Log.Debug(FileDirectoryHandler.class, exception.getMessage()); 273 } 274 } 275 return lstFiles.toArray(new File[0]); 276 } 277 278 /** 279 * 280 * @param directory 281 * @param identifier 282 * @return A File array with the files (not directories) within the given directory 283 */ 284 @SuppressWarnings("unchecked") 285 public static File[] getFilesOfDirectory(String directory, String identifier) { 286 File src; 287 ArrayList<File> lstFiles = null; 288 try { 289 lstFiles = new ArrayList<java.io.File>(); 290 src = new File(directory); 291 Log.Debug(FileDirectoryHandler.class, "Verzeichnis: " + src); 292 File[] files = src.listFiles(); 293 Log.Debug(FileDirectoryHandler.class, "Dateien analysieren..."); 294 lstFiles = new ArrayList<java.io.File>(); 295 if (files != null && files.length > 0) { 296 for (int i = 0, k = 0; i < files.length; i++) { 297// Log.Debug(this,"Datei analysieren: " + files[i].getName()); 298 if (files[i].isFile() && (identifier == null || files[i].toString().contains(identifier))) { 299 try { 300 lstFiles.add(files[i]); 301 Log.Debug(FileDirectoryHandler.class, "Datei gefunden: " + files[i].getName()); 302 k++; 303 } catch (Exception ex) { 304 Log.Debug(FileDirectoryHandler.class, ex.getMessage()); 305 } 306 } 307 } 308 } else { 309 Log.Debug(FileDirectoryHandler.class, "Keine Datei gefunden."); 310 } 311 } catch (Exception exception) { 312 Log.Debug(FileDirectoryHandler.class, exception); 313 Log.Debug(FileDirectoryHandler.class, exception.getMessage()); 314 } 315 return lstFiles.toArray(new File[0]); 316 } 317 318 /** 319 * Open a file in default app or as "save as" dialog, depending on the platform 320 * @param file 321 */ 322 public static void open(File file) { 323 if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) { 324 try { 325 Desktop.getDesktop().open(file); 326 } catch (Exception ex) { 327 Log.Debug(FileDirectoryHandler.class, ex.getMessage()); 328 Popup.notice(Messages.FILE_OPEN_FAILED + file.getPath()); 329 } 330 } else { 331 new DialogForFile().saveFile(file); 332 } 333 } 334 335 /** 336 * Edit a file in default app or as "save as" dialog, depending on the platform 337 * @param file 338 */ 339 public static void edit(File file) { 340 if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.EDIT)) { 341 try { 342 Desktop.getDesktop().edit(file); 343 } catch (Exception ex) { 344 Log.Debug(FileDirectoryHandler.class, ex.getMessage()); 345 Popup.notice(Messages.FILE_OPEN_FAILED + file.getPath()); 346 } 347 } else { 348 new DialogForFile(DialogForFile.FILES_ONLY).saveFile(file); 349 } 350 } 351 352 public static void save(File file) { 353 DialogForFile d = new DialogForFile(DialogForFile.FILES_ONLY, new File(file.getName())); 354 d.saveFile(file); 355 } 356 357 /** 358 * Copies a file to a temporary file. The resulting file is NOT linked 359 * to the original one and even the original file is locked, 360 * the resulting file is not 361 * @param file 362 * @return The file with a randomly generated suffix 363 */ 364 public static File tempFileClone(File file) { 365 return tempFileClone(file, new RandomText(3).getString()); 366 } 367 368 /** 369 * Copies a file to a temporary file. The resulting file is NOT linked 370 * to the original one and even the original file is locked, 371 * the resulting file is not 372 * @param file 373 * @param suffix 374 * @return 375 */ 376 public static File tempFileClone(File file, String suffix) { 377 try { 378 suffix = check(suffix); 379 cacheCheck(); 380 File fil = new File(copyFile(file, new File(LocalSettings.getProperty(LocalSettings.CACHE_DIR)), new RandomText().getString() + "." + suffix, true)); 381 fil.deleteOnExit(); 382 return fil; 383 } catch (IOException ex) { 384 Log.Debug(FileDirectoryHandler.class, ex); 385 } 386 return null; 387 } 388 389 /** 390 * Returns a completely random named temporay file 391 * @param suffix no '.' please 392 * @return 393 */ 394 public static File getTempFile(String suffix) { 395 suffix = check(suffix); 396 return getTempFile(new RandomText(18).getString(), suffix); 397 } 398 399 /** 400 * 401 * @return A temporary file with MP suffix (~mp) 402 */ 403 public static File getTempFile() { 404 return getTempFile("~yabs"); 405 } 406 407 /** 408 * 409 * @param filename 410 * @param suffix 411 * @return A temporay file with the given name 412 */ 413 public static File getTempFile(String filename, String suffix) { 414 cacheCheck(); 415 filename = check(filename); 416 suffix = check(suffix); 417 File fil = new File(LocalSettings.getProperty(LocalSettings.CACHE_DIR) + File.separator + filename + "." + suffix); 418 fil.deleteOnExit(); 419 return fil; 420 } 421 422 /** 423 * 424 * @return The temporary directory + File.separator 425 */ 426 public static String getTempDir() { 427 cacheCheck(); 428 return LocalSettings.getProperty(LocalSettings.CACHE_DIR) + File.separator; 429 } 430 431 /** 432 * 433 * @return The temporary directory 434 */ 435 public static String getTempDir2() { 436 cacheCheck(); 437 return LocalSettings.getProperty(LocalSettings.CACHE_DIR); 438 } 439 440 /** 441 * 442 * @return The temporary directory as File object 443 */ 444 public static File getTempDirAsFile() { 445 cacheCheck(); 446 return new File(LocalSettings.getProperty(LocalSettings.CACHE_DIR)); 447 } 448 449 /** 450 * Downloads a file 451 * @param address 452 * @param localFileName 453 * @return 454 * Marco Schmidt 455 */ 456 public static File download(String address, String localFileName) { 457 localFileName = check(localFileName); 458 OutputStream out = null; 459 URLConnection conn = null; 460 InputStream in = null; 461 try { 462 URL url = new URL(address); 463 out = new BufferedOutputStream( 464 new FileOutputStream(localFileName)); 465 conn = url.openConnection(); 466 in = conn.getInputStream(); 467 byte[] buffer = new byte[1024]; 468 int numRead; 469 long numWritten = 0; 470 while ((numRead = in.read(buffer)) != -1) { 471 out.write(buffer, 0, numRead); 472 numWritten += numRead; 473 } 474 Log.Debug(FileDirectoryHandler.class, localFileName + "\t" + numWritten); 475 } catch (Exception exception) { 476 Log.Debug(FileDirectoryHandler.class, exception); 477 } finally { 478 try { 479 if (in != null) { 480 in.close(); 481 } 482 if (out != null) { 483 out.close(); 484 } 485 } catch (IOException ioe) { 486 } 487 } 488 File file = new File(localFileName); 489// file.deleteOnExit(); 490 return file; 491 } 492 493 /** 494 * Downloads a file 495 * @param address 496 * @return 497 */ 498 public static File download(String address) { 499 int lastSlashIndex = address.lastIndexOf('/'); 500 if (lastSlashIndex >= 0 501 && lastSlashIndex < address.length() - 1) { 502 return download(address, address.substring(lastSlashIndex + 1)); 503 } else { 504 Log.Debug(FileDirectoryHandler.class, "Could not figure out local file name for " 505 + address); 506 } 507 return null; 508 } 509 510 /** 511 * Copies a file via streaming 512 * @param sourceFile 513 * @param outp 514 * @param silent 515 * @return 516 * @throws java.io.FileNotFoundException 517 * @throws java.io.IOException 518 */ 519 public static URI copyFile(File sourceFile, File outp, boolean silent) throws FileNotFoundException, IOException { 520 InputStream in = new FileInputStream(sourceFile); 521 522 OutputStream out = new FileOutputStream(outp); 523 524 // Copy the bits from instream to outstream 525 byte[] buf = new byte[1024]; 526 int len; 527 while ((len = in.read(buf)) > 0) { 528 out.write(buf, 0, len); 529 } 530 in.close(); 531 out.close(); 532 533 if (!silent) { 534 Notificator.raiseNotification(Messages.FILE_SAVED + " " + outp.getPath(), false); 535 } 536 537 return outp.toURI(); 538 } 539 540 /** 541 * Copies a file via streaming 542 * @param sourceFile 543 * @param outp 544 * @return 545 * @throws java.io.FileNotFoundException 546 * @throws java.io.IOException 547 */ 548 public static URI copyFile(File sourceFile, File outp) throws FileNotFoundException, IOException { 549 return copyFile(sourceFile, outp, true); 550 } 551 552 private static void cacheCheck() { 553 File e = null; 554 try { 555 e = new File(LocalSettings.getProperty(LocalSettings.CACHE_DIR)); 556 } catch (Exception ex) {//avoid npe 557 Log.Debug(ex); 558 LocalSettings.setProperty(LocalSettings.CACHE_DIR, Constants.FALLBACK_CACHE_DIR); 559 e = new File(Constants.FALLBACK_CACHE_DIR); 560 } 561 if (!e.exists()) { 562 e.mkdirs(); 563 } 564 //Cannot access Cache dir? 565 if (!e.isDirectory() || !e.canWrite() || e.listFiles() == null) { 566 LocalSettings.setProperty(LocalSettings.CACHE_DIR, Constants.FALLBACK_CACHE_DIR); 567 cacheCheck(); 568 try { 569 FileDirectoryHandler.deleteTreeOnExit(getTempDirAsFile()); 570 } catch (IOException ex) { 571 Log.Debug(ex); 572 } 573 } 574 } 575 576 private static synchronized String check(String filename) { 577 return filename.replaceAll("[?:\\\\/*\\\"\\\"<>|]", "-").replace("..", "."); 578 } 579 580 /** 581 * Unzips the file (if it is a zip file, returns the original file if it is not a zip file). 582 * If the given file is a zip file containing multiple files, returns a temporary directory containing the extracted files. 583 * @param file 584 * @return 585 */ 586 public static File unzipFile(File file) { 587 if (file.getName().endsWith(".zip") || file.getName().endsWith(".jar")) { 588 File c = getnewTemporaryDirectory(); 589 UnZip.deflate(file.getPath(), c.getPath()); 590 if (c.listFiles().length == 1) { 591 File k = c.listFiles()[0]; 592 if (k.isFile()) { 593 return k; 594 } else if (k.listFiles().length == 1) { 595 return (k.listFiles()[0].isFile()) ? k.listFiles()[0] : c; 596 } 597 } 598 599 return c; 600 } else { 601 return file; 602 } 603 } 604 605 /** 606 * Creates a new, RW, temporary directory within the cache directory 607 * @return 608 */ 609 public static File getnewTemporaryDirectory() { 610 File f = getTempDirAsFile(); 611 File t = new File(f.getPath() + File.separator + RandomText.getText() + File.separator + RandomText.getText()); 612 t.mkdirs(); 613 t.getParentFile().setWritable(true); 614 t.getParentFile().setReadable(true); 615 return t; 616 } 617 618 /** 619 * Deletes the content of a directory, omitting files which contain $omit in their name 620 * No Subdirectories are deleted! 621 * @param path 622 * @param omit 623 * @throws IOException 624 */ 625 public static void deleteDirectoryContent(File path, String... omit) throws IOException { 626 for (File file : path.listFiles()) { 627 List<String> o = Arrays.asList(omit); 628 String name = file.getName(); 629 boolean rd = true; 630 for (int i = 0; i < o.size(); i++) { 631 String string = o.get(i); 632 if (name.toLowerCase().contains(string.toLowerCase())) { 633 rd = false; 634 } 635 } 636 if (rd) { 637 file.delete(); 638 } 639 } 640 } 641 642 /** 643 * Deletes the content of a directory, omitting files which contain $omit in their name 644 * ALL Subdirectories are deleted! 645 * @param path 646 * @param omit 647 * @throws IOException 648 */ 649 public static void deleteDirectoryContent2(File path, String... omit) throws IOException { 650 for (File file : path.listFiles()) { 651 if (file.isDirectory()) { 652 deleteDirectoryContent2(file, omit); 653 } 654 List<String> o = Arrays.asList(omit); 655 String name = file.getName(); 656 boolean rd = true; 657 for (int i = 0; i < o.size(); i++) { 658 String string = o.get(i); 659 if (name.toLowerCase().contains(string.toLowerCase())) { 660 rd = false; 661 } 662 } 663 if (rd) { 664 file.delete(); 665 } 666 } 667 } 668}