1
2
3
4
5
6
7 package org.mule.util;
8
9 import org.mule.api.MuleRuntimeException;
10 import org.mule.config.i18n.MessageFactory;
11
12 import java.io.BufferedOutputStream;
13 import java.io.BufferedWriter;
14 import java.io.File;
15 import java.io.FileInputStream;
16 import java.io.FileNotFoundException;
17 import java.io.FileOutputStream;
18 import java.io.FileWriter;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.OutputStream;
22 import java.io.UnsupportedEncodingException;
23 import java.net.JarURLConnection;
24 import java.net.URI;
25 import java.net.URL;
26 import java.net.URLConnection;
27 import java.net.URLDecoder;
28 import java.nio.channels.Channel;
29 import java.nio.channels.FileChannel;
30 import java.util.Enumeration;
31 import java.util.jar.JarEntry;
32 import java.util.jar.JarFile;
33 import java.util.zip.ZipEntry;
34 import java.util.zip.ZipFile;
35
36 import org.apache.commons.lang.StringUtils;
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40
41
42
43
44
45 public class FileUtils extends org.apache.commons.io.FileUtils
46 {
47 private static final Log logger = LogFactory.getLog(FileUtils.class);
48 public static String DEFAULT_ENCODING = "UTF-8";
49
50 public static synchronized void copyStreamToFile(InputStream input, File destination) throws IOException
51 {
52 if (destination.exists() && !destination.canWrite())
53 {
54 throw new IOException("Destination file does not exist or is not writeable");
55 }
56
57 try
58 {
59 FileOutputStream output = new FileOutputStream(destination);
60 try
61 {
62 IOUtils.copy(input, output);
63 }
64 finally
65 {
66 IOUtils.closeQuietly(output);
67 }
68 }
69 finally
70 {
71 IOUtils.closeQuietly(input);
72 }
73 }
74
75
76 public static File createFile(String filename) throws IOException
77 {
78 File file = FileUtils.newFile(filename);
79 if (!file.canWrite())
80 {
81 String dirName = file.getPath();
82 int i = dirName.lastIndexOf(File.separator);
83 if (i > -1)
84 {
85 dirName = dirName.substring(0, i);
86 File dir = FileUtils.newFile(dirName);
87 dir.mkdirs();
88 }
89 file.createNewFile();
90 }
91 return file;
92 }
93
94
95 public static String prepareWinFilename(String filename)
96 {
97 filename = filename.replaceAll("<", "(");
98 filename = filename.replaceAll(">", ")");
99 filename = filename.replaceAll("[/\\*?|:;\\]\\[\"]", "-");
100 return filename;
101 }
102
103
104 public static File openDirectory(String directory) throws IOException
105 {
106 File dir = FileUtils.newFile(directory);
107 if (!dir.exists())
108 {
109 dir.mkdirs();
110 }
111 if (!dir.isDirectory() || !dir.canRead())
112 {
113 throw new IOException("Path: " + directory + " exists but isn't a directory");
114 }
115 return dir;
116 }
117
118
119
120
121
122
123
124
125
126 public static File stringToFile(String filename, String data) throws IOException
127 {
128 return stringToFile(filename, data, false);
129 }
130
131
132 public static synchronized File stringToFile(String filename, String data, boolean append)
133 throws IOException
134 {
135 return stringToFile(filename, data, append, false);
136 }
137
138
139 public static synchronized File stringToFile(String filename, String data, boolean append, boolean newLine)
140 throws IOException
141 {
142 File f = createFile(filename);
143 BufferedWriter writer = null;
144 try
145 {
146 writer = new BufferedWriter(new FileWriter(f, append));
147 writer.write(data);
148 if (newLine)
149 {
150 writer.newLine();
151 }
152 }
153 finally
154 {
155 if (writer != null)
156 {
157 writer.close();
158 }
159 }
160 return f;
161 }
162
163
164 public static String getResourcePath(String resourceName, Class callingClass) throws IOException
165 {
166 return getResourcePath(resourceName, callingClass, DEFAULT_ENCODING);
167 }
168
169
170 public static String getResourcePath(String resourceName, Class callingClass, String encoding)
171 throws IOException
172 {
173 if (resourceName == null)
174 {
175
176 return null;
177 }
178
179 URL url = IOUtils.getResourceAsUrl(resourceName, callingClass);
180 if (url == null)
181 {
182
183 return null;
184 }
185 return normalizeFilePath(url, encoding);
186 }
187
188
189
190
191
192
193
194
195
196
197 public static String normalizeFilePath(URL url, String encoding) throws UnsupportedEncodingException
198 {
199 String resource = URLDecoder.decode(url.toExternalForm(), encoding);
200 if (resource != null)
201 {
202 if (resource.startsWith("file:/"))
203 {
204 resource = resource.substring(6);
205
206 if (!resource.startsWith(File.separator))
207 {
208 resource = File.separator + resource;
209 }
210 }
211 }
212 return resource;
213 }
214
215
216
217
218
219
220
221 public static boolean deleteTree(File dir)
222 {
223 return deleteTree(dir, null);
224 }
225
226
227
228
229
230
231
232
233
234
235
236 public static boolean deleteTree(File dir, final String[] topLevelDirsToIgnore)
237 {
238 if (dir == null || !dir.exists())
239 {
240 return true;
241 }
242 File[] files = dir.listFiles();
243 if (files != null)
244 {
245 for (int i = 0; i < files.length; i++)
246 {
247 OUTER:
248 if (files[i].isDirectory())
249 {
250 if (topLevelDirsToIgnore != null)
251 {
252 for (int j = 0; j < topLevelDirsToIgnore.length; j++)
253 {
254 String ignored = topLevelDirsToIgnore[j];
255 if (ignored.equals(FilenameUtils.getBaseName(files[i].getName())))
256 {
257 break OUTER;
258 }
259 }
260 }
261 if (!deleteTree(files[i]))
262 {
263 return false;
264 }
265 }
266 else
267 {
268 if (!files[i].delete())
269 {
270 return false;
271 }
272 }
273 }
274 }
275 return dir.delete();
276 }
277
278
279
280
281 public static void unzip(File archive, File directory) throws IOException
282 {
283 ZipFile zip = null;
284
285 if (directory.exists())
286 {
287 if (!directory.isDirectory())
288 {
289 throw new IOException("Directory is not a directory: " + directory);
290 }
291 }
292 else
293 {
294 if (!directory.mkdirs())
295 {
296 throw new IOException("Could not create directory: " + directory);
297 }
298 }
299 try
300 {
301 zip = new ZipFile(archive);
302 for (Enumeration entries = zip.entries(); entries.hasMoreElements();)
303 {
304 ZipEntry entry = (ZipEntry) entries.nextElement();
305 File f = FileUtils.newFile(directory, entry.getName());
306 if (entry.isDirectory())
307 {
308 if (!f.exists() && !f.mkdirs())
309 {
310 throw new IOException("Could not create directory: " + f);
311 }
312 }
313 else
314 {
315 InputStream is = zip.getInputStream(entry);
316 OutputStream os = new BufferedOutputStream(new FileOutputStream(f));
317 IOUtils.copy(is, os);
318 IOUtils.closeQuietly(is);
319 IOUtils.closeQuietly(os);
320 }
321 }
322 }
323 finally
324 {
325 if (zip != null)
326 {
327 zip.close();
328 }
329 }
330 }
331
332
333
334
335
336
337
338
339
340
341
342 public static File newFile(String pathName)
343 {
344 try
345 {
346 return new File(pathName).getCanonicalFile();
347 }
348 catch (IOException e)
349 {
350 throw new MuleRuntimeException(
351 MessageFactory.createStaticMessage("Unable to create a canonical file for " + pathName),
352 e);
353 }
354 }
355
356
357
358
359
360
361
362
363
364
365
366 public static File newFile(URI uri)
367 {
368 try
369 {
370 return new File(uri).getCanonicalFile();
371 }
372 catch (IOException e)
373 {
374 throw new MuleRuntimeException(
375 MessageFactory.createStaticMessage("Unable to create a canonical file for " + uri),
376 e);
377 }
378 }
379
380
381
382
383
384
385
386
387
388
389
390 public static File newFile(File parent, String child)
391 {
392 try
393 {
394 return new File(parent, child).getCanonicalFile();
395 }
396 catch (IOException e)
397 {
398 throw new MuleRuntimeException(
399 MessageFactory.createStaticMessage("Unable to create a canonical file for parent: "
400 + parent + " and child: " + child),
401 e);
402 }
403 }
404
405
406
407
408
409
410
411
412
413
414
415 public static File newFile(String parent, String child)
416 {
417 try
418 {
419 return new File(parent, child).getCanonicalFile();
420 }
421 catch (IOException e)
422 {
423 throw new MuleRuntimeException(
424 MessageFactory.createStaticMessage("Unable to create a canonical file for parent: "
425 + parent + " and child: " + child),
426 e);
427 }
428 }
429
430
431
432
433
434
435
436
437
438
439
440 public static void extractResources(String resourceName, Class callingClass, File outputDir, boolean keepParentDirectory) throws IOException
441 {
442 URL url = callingClass.getClassLoader().getResource(resourceName);
443 URLConnection connection = url.openConnection();
444 if (connection instanceof JarURLConnection)
445 {
446 extractJarResources((JarURLConnection) connection, outputDir, keepParentDirectory);
447 }
448 else
449 {
450 extractFileResources(normalizeFilePath(url, DEFAULT_ENCODING),
451 outputDir, resourceName, keepParentDirectory);
452 }
453 }
454
455
456
457
458
459
460
461
462
463
464 private static void extractFileResources(String path, File outputDir, String resourceName, boolean keepParentDirectory) throws IOException
465 {
466 File file = FileUtils.newFile(path);
467 if (!file.exists())
468 {
469 throw new IOException("The resource by path " + path + " ");
470 }
471 if (file.isDirectory())
472 {
473 if (keepParentDirectory)
474 {
475 outputDir = FileUtils.newFile(outputDir.getPath() + File.separator + resourceName);
476 if (!outputDir.exists())
477 {
478 outputDir.mkdirs();
479 }
480 }
481 else
482 {
483 outputDir = FileUtils.newFile(outputDir.getPath());
484 }
485 copyDirectory(file, outputDir);
486 }
487 else
488 {
489
490 if (keepParentDirectory)
491 {
492 outputDir = FileUtils.newFile(outputDir.getPath() + File.separator + resourceName);
493 }
494 else
495 {
496 outputDir = FileUtils.newFile(outputDir.getPath() + File.separator + file.getName());
497 }
498 copyFile(file, outputDir);
499 }
500 }
501
502
503
504
505
506
507
508
509
510 private static void extractJarResources(JarURLConnection connection, File outputDir, boolean keepParentDirectory) throws IOException
511 {
512 JarFile jarFile = connection.getJarFile();
513 JarEntry jarResource = connection.getJarEntry();
514 Enumeration entries = jarFile.entries();
515 InputStream inputStream = null;
516 OutputStream outputStream = null;
517 int jarResourceNameLenght = jarResource.getName().length();
518 for (; entries.hasMoreElements();)
519 {
520 JarEntry entry = (JarEntry) entries.nextElement();
521 if (entry.getName().startsWith(jarResource.getName()))
522 {
523
524 String path = outputDir.getPath() + File.separator + entry.getName();
525
526
527 if (!keepParentDirectory)
528 {
529 if (entry.isDirectory())
530 {
531 if (entry.getName().equals(jarResource.getName()))
532 {
533 continue;
534 }
535 path = outputDir.getPath() + File.separator + entry.getName().substring(jarResourceNameLenght, entry.getName().length());
536 }
537 else
538 {
539 if (entry.getName().length() > jarResourceNameLenght)
540 {
541 path = outputDir.getPath() + File.separator + entry.getName().substring(jarResourceNameLenght, entry.getName().length());
542 }
543 else
544 {
545 path = outputDir.getPath() + File.separator + entry.getName().substring(entry.getName().lastIndexOf("/"), entry.getName().length());
546 }
547 }
548 }
549
550 File file = FileUtils.newFile(path);
551 if (!file.getParentFile().exists())
552 {
553 if (!file.getParentFile().mkdirs())
554 {
555 throw new IOException("Could not create directory: " + file.getParentFile());
556 }
557 }
558 if (entry.isDirectory())
559 {
560 if (!file.exists() && !file.mkdirs())
561 {
562 throw new IOException("Could not create directory: " + file);
563 }
564
565 }
566 else
567 {
568 try
569 {
570 inputStream = jarFile.getInputStream(entry);
571 outputStream = new BufferedOutputStream(new FileOutputStream(file));
572 IOUtils.copy(inputStream, outputStream);
573 }
574 finally
575 {
576 IOUtils.closeQuietly(inputStream);
577 IOUtils.closeQuietly(outputStream);
578 }
579 }
580
581 }
582 }
583 }
584
585 public static boolean renameFileHard(String srcFilePath, String destFilePath)
586 {
587 if (StringUtils.isNotBlank(srcFilePath) && StringUtils.isNotBlank(destFilePath))
588 {
589 return renameFileHard(new File(srcFilePath), new File(destFilePath));
590 }
591 else
592 {
593 return false;
594 }
595 }
596
597 public static boolean renameFileHard(File srcFile, File destFile)
598 {
599 boolean isRenamed = false;
600 if (srcFile != null && destFile != null)
601 {
602 logger.debug("Moving file " + srcFile.getAbsolutePath() + " to " + destFile.getAbsolutePath());
603 if (!destFile.exists())
604 {
605 try
606 {
607 if (srcFile.isFile())
608 {
609 logger.debug("Trying to rename file");
610 FileInputStream in = null;
611 FileOutputStream out = null;
612 try
613 {
614 in = new FileInputStream(srcFile);
615 out = new FileOutputStream(destFile);
616 out.getChannel().transferFrom(in.getChannel(), 0, srcFile.length());
617 isRenamed = true;
618 }
619 catch (Exception e)
620 {
621 logger.debug(e);
622 }
623 finally
624 {
625 if (in != null)
626 {
627 try
628 {
629 in.close();
630 }
631 catch (Exception inNotClosed)
632 {
633 logger.debug(inNotClosed);
634 }
635 }
636 if (out != null)
637 {
638 try
639 {
640 out.close();
641 }
642 catch (Exception outNotClosed)
643 {
644 logger.debug(outNotClosed);
645 }
646 }
647 }
648 logger.debug("File renamed: " + isRenamed);
649 if (isRenamed)
650 {
651 srcFile.delete();
652 }
653 else
654 {
655 destFile.delete();
656 }
657 }
658 else
659 {
660 logger.debug(srcFile.getAbsolutePath() + " is not a valid file.");
661 }
662 }
663 catch (Exception e)
664 {
665 logger.debug("Error renaming file from " + srcFile.getAbsolutePath() + " to " + destFile.getAbsolutePath());
666 }
667 }
668 else
669 {
670 logger.debug("Error renaming file " + srcFile.getAbsolutePath() + ". Destination file " + destFile.getAbsolutePath() + " already exists.");
671 }
672 }
673 return isRenamed;
674 }
675
676 public static boolean renameFile(String srcFilePath, String destFilePath)
677 {
678 if (StringUtils.isNotBlank(srcFilePath) && StringUtils.isNotBlank(destFilePath))
679 {
680 return renameFile(new File(srcFilePath), new File(destFilePath));
681 }
682 else
683 {
684 return false;
685 }
686 }
687
688 public static boolean renameFile(File srcFile, File destFile)
689 {
690 boolean isRenamed = false;
691 if (srcFile != null && destFile != null)
692 {
693 logger.debug("Moving file " + srcFile.getAbsolutePath() + " to " + destFile.getAbsolutePath());
694 if (!destFile.exists())
695 {
696 try
697 {
698 if (srcFile.isFile())
699 {
700 logger.debug("Trying to rename file");
701 isRenamed = srcFile.renameTo(destFile);
702 if (!isRenamed && srcFile.exists())
703 {
704 logger.debug("Trying hard copy, assuming partition crossing ...");
705 isRenamed = renameFileHard(srcFile, destFile);
706 }
707 logger.debug("File renamed: " + isRenamed);
708 }
709 else
710 {
711 logger.debug(srcFile.getAbsolutePath() + " is not a valid file");
712 }
713 }
714 catch (Exception e)
715 {
716 logger.debug("Error moving file from " + srcFile.getAbsolutePath() + " to " + destFile.getAbsolutePath(), e);
717 }
718 }
719 else
720 {
721 logger.debug("Error renaming file " + srcFile.getAbsolutePath() + ". Destination file " + destFile.getAbsolutePath() + " already exists.");
722 }
723 }
724 else
725 {
726 logger.debug("Error renaming file. Source or destination file is null.");
727 }
728
729 return isRenamed;
730 }
731
732
733
734
735 public static boolean moveFileWithCopyFallback(File sourceFile, File destinationFile)
736 {
737
738 boolean success = sourceFile.renameTo(destinationFile);
739
740 if (!success)
741 {
742
743 FileInputStream fis = null;
744 FileOutputStream fos = null;
745 try
746 {
747 fis = new FileInputStream(sourceFile);
748 fos = new FileOutputStream(destinationFile);
749 FileChannel srcChannel = fis.getChannel();
750 FileChannel dstChannel = fos.getChannel();
751 dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
752 srcChannel.close();
753 dstChannel.close();
754 success = sourceFile.delete();
755 }
756 catch (IOException ioex)
757 {
758
759 success = false;
760 }
761 finally
762 {
763 IOUtils.closeQuietly(fis);
764 IOUtils.closeQuietly(fos);
765 }
766 }
767
768 return success;
769 }
770
771
772
773
774
775
776
777
778
779
780 public static void safeCopyFile(File in, File out) throws IOException
781 {
782 try
783 {
784 FileInputStream fis = new FileInputStream(in);
785 FileOutputStream fos = new FileOutputStream(out);
786 try
787 {
788 byte[] buf = new byte[1024];
789 int i = 0;
790 while ((i = fis.read(buf)) != -1)
791 {
792 fos.write(buf, 0, i);
793 }
794 }
795 catch (IOException e)
796 {
797 throw e;
798 }
799 finally
800 {
801 try
802 {
803 if (fis != null) fis.close();
804 if (fos != null) fos.close();
805 }
806 catch (IOException e)
807 {
808 throw e;
809 }
810
811 }
812 }
813 catch (FileNotFoundException e)
814 {
815 throw e;
816 }
817 }
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839 public static void copyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException
840 {
841 if (srcFile == null)
842 {
843 throw new NullPointerException("Source must not be null");
844 }
845 if (destFile == null)
846 {
847 throw new NullPointerException("Destination must not be null");
848 }
849 if (srcFile.exists() == false)
850 {
851 throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
852 }
853 if (srcFile.isDirectory())
854 {
855 throw new IOException("Source '" + srcFile + "' exists but is a directory");
856 }
857 if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath()))
858 {
859 throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same");
860 }
861 if (destFile.getParentFile() != null && destFile.getParentFile().exists() == false)
862 {
863 if (destFile.getParentFile().mkdirs() == false)
864 {
865 throw new IOException("Destination '" + destFile + "' directory cannot be created");
866 }
867 }
868 if (destFile.exists() && destFile.canWrite() == false)
869 {
870 throw new IOException("Destination '" + destFile + "' exists but is read-only");
871 }
872 doCopyFile(srcFile, destFile, preserveFileDate);
873 }
874
875
876
877
878
879
880
881
882
883 private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException
884 {
885 if (destFile.exists() && destFile.isDirectory())
886 {
887 throw new IOException("Destination '" + destFile + "' exists but is a directory");
888 }
889
890 FileChannel input = new FileInputStream(srcFile).getChannel();
891 try
892 {
893 FileChannel output = new FileOutputStream(destFile).getChannel();
894 try
895 {
896 output.transferFrom(input, 0, input.size());
897 }
898 finally
899 {
900 closeQuietly(output);
901 }
902 }
903 finally
904 {
905 closeQuietly(input);
906 }
907
908 if (srcFile.length() != destFile.length())
909 {
910 throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'");
911 }
912 if (preserveFileDate)
913 {
914 destFile.setLastModified(srcFile.lastModified());
915 }
916 }
917
918
919
920
921
922
923
924
925
926 public static void closeQuietly(Channel channel)
927 {
928 try
929 {
930 if (channel != null)
931 {
932 channel.close();
933 }
934 }
935 catch (IOException ioe)
936 {
937
938 }
939 }
940
941 public static boolean isFile(URL url)
942 {
943 return "file".equals(url.getProtocol());
944 }
945
946
947
948
949
950
951
952
953 public static long getFileTimeStamp(URL url)
954 {
955 long timeStamp = -1;
956
957 if (isFile(url))
958 {
959 timeStamp = new File(url.getFile()).lastModified();
960 }
961
962 return timeStamp;
963 }
964 }