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