1 package org.apache.maven.shared.utils.io;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.shared.utils.Os;
23 import org.apache.maven.shared.utils.StringUtils;
24
25 import javax.annotation.Nonnull;
26 import javax.annotation.Nullable;
27 import javax.annotation.WillClose;
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.FileOutputStream;
32 import java.io.FileReader;
33 import java.io.FileWriter;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.InputStreamReader;
37 import java.io.OutputStream;
38 import java.io.OutputStreamWriter;
39 import java.io.Reader;
40 import java.io.Writer;
41 import java.net.URL;
42 import java.nio.channels.FileChannel;
43 import java.security.SecureRandom;
44 import java.text.DecimalFormat;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Collections;
48 import java.util.List;
49 import java.util.Random;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public class FileUtils
89 {
90 protected FileUtils()
91 {
92
93 }
94
95
96
97
98 private static final int ONE_KB = 1024;
99
100
101
102
103 private static final int ONE_MB = ONE_KB * ONE_KB;
104
105
106
107
108 private static final int ONE_GB = ONE_KB * ONE_MB;
109
110
111
112
113 private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 30;
114
115
116
117
118 private static final String FS = System.getProperty( "file.separator" );
119
120
121
122
123
124
125
126 private static final String[] INVALID_CHARACTERS_FOR_WINDOWS_FILE_NAME = { ":", "*", "?", "\"", "<", ">", "|" };
127
128
129
130
131
132 @Nonnull public static String[] getDefaultExcludes()
133 {
134 return DirectoryScanner.DEFAULTEXCLUDES;
135 }
136
137
138
139
140
141 @Nonnull public static List<String> getDefaultExcludesAsList()
142 {
143 return Arrays.asList( getDefaultExcludes() );
144 }
145
146
147
148
149
150
151 @Nonnull public static String getDefaultExcludesAsString()
152 {
153 return StringUtils.join( DirectoryScanner.DEFAULTEXCLUDES, "," );
154 }
155
156
157
158
159
160
161
162
163 @Nonnull public static String dirname( @Nonnull String filename )
164 {
165 int i = filename.lastIndexOf( File.separator );
166 return ( i >= 0 ? filename.substring( 0, i ) : "" );
167 }
168
169
170
171
172
173
174
175 @Nonnull public static String filename( @Nonnull String filename )
176 {
177 int i = filename.lastIndexOf( File.separator );
178 return ( i >= 0 ? filename.substring( i + 1 ) : filename );
179 }
180
181
182
183
184
185
186
187
188
189 @Nonnull public static String extension( @Nonnull String filename )
190 {
191
192 int lastSep = filename.lastIndexOf( File.separatorChar );
193 int lastDot;
194 if ( lastSep < 0 )
195 {
196 lastDot = filename.lastIndexOf( '.' );
197 }
198 else
199 {
200 lastDot = filename.substring( lastSep + 1 ).lastIndexOf( '.' );
201 if ( lastDot >= 0 )
202 {
203 lastDot += lastSep + 1;
204 }
205 }
206
207 if ( lastDot >= 0 && lastDot > lastSep )
208 {
209 return filename.substring( lastDot + 1 );
210 }
211
212 return "";
213 }
214
215
216
217
218
219
220
221 public static boolean fileExists( @Nonnull String fileName )
222 {
223 File file = new File( fileName );
224 return file.exists();
225 }
226
227
228
229
230
231
232
233
234 @Nonnull public static String fileRead( @Nonnull String file )
235 throws IOException
236 {
237 return fileRead( file, null );
238 }
239
240
241
242
243
244
245
246 @Nonnull private static String fileRead( @Nonnull String file, @Nullable String encoding )
247 throws IOException
248 {
249 return fileRead( new File( file ), encoding );
250 }
251
252
253
254
255
256
257
258
259 @Nonnull public static String fileRead( @Nonnull File file )
260 throws IOException
261 {
262 return fileRead( file, null );
263 }
264
265
266
267
268
269
270
271 @Nonnull public static String fileRead( @Nonnull File file, @Nullable String encoding )
272 throws IOException
273 {
274 StringBuilder buf = new StringBuilder();
275
276 Reader reader = null;
277
278 try
279 {
280 if ( encoding != null )
281 {
282 reader = new InputStreamReader( new FileInputStream( file ), encoding );
283 }
284 else
285 {
286 reader = new InputStreamReader( new FileInputStream( file ) );
287 }
288 int count;
289 char[] b = new char[512];
290 while ( ( count = reader.read( b ) ) > 0 )
291 {
292 buf.append( b, 0, count );
293 }
294 }
295 finally
296 {
297 IOUtil.close( reader );
298 }
299
300 return buf.toString();
301 }
302
303
304
305
306
307
308
309 @Nonnull public static String[] fileReadArray( @Nonnull File file )
310 throws IOException
311 {
312 List<String> files = loadFile( file );
313
314 return files.toArray( new String[files.size()] );
315 }
316
317
318
319
320
321
322
323
324
325 public static void fileAppend( @Nonnull String fileName, @Nonnull String data )
326 throws IOException
327 {
328 fileAppend( fileName, null, data );
329 }
330
331
332
333
334
335
336
337
338
339 public static void fileAppend( @Nonnull String fileName, @Nullable String encoding, @Nonnull String data )
340 throws IOException
341 {
342 FileOutputStream out = null;
343 try
344 {
345 out = new FileOutputStream( fileName, true );
346 if ( encoding != null )
347 {
348 out.write( data.getBytes( encoding ) );
349 }
350 else
351 {
352 out.write( data.getBytes() );
353 }
354 }
355 finally
356 {
357 IOUtil.close( out );
358 }
359 }
360
361
362
363
364
365
366
367
368
369 public static void fileWrite( @Nonnull String fileName, @Nonnull String data )
370 throws IOException
371 {
372 fileWrite( fileName, null, data );
373 }
374
375
376
377
378
379
380
381
382
383 public static void fileWrite( @Nonnull String fileName, @Nullable String encoding, @Nonnull String data )
384 throws IOException
385 {
386 File file = new File( fileName );
387 fileWrite( file, encoding, data );
388 }
389
390
391
392
393
394
395
396
397
398 public static void fileWrite( @Nonnull File file, @Nullable String encoding, @Nonnull String data )
399 throws IOException
400 {
401 Writer writer = null;
402 try
403 {
404 OutputStream out = new FileOutputStream( file );
405 if ( encoding != null )
406 {
407 writer = new OutputStreamWriter( out, encoding );
408 }
409 else
410 {
411 writer = new OutputStreamWriter( out );
412 }
413 writer.write( data );
414 }
415 finally
416 {
417 IOUtil.close( writer );
418 }
419 }
420
421
422
423
424
425
426
427
428
429 public static void fileWriteArray( @Nonnull File file, @Nullable String... data )
430 throws IOException
431 {
432 fileWriteArray( file, null, data );
433 }
434
435
436
437
438
439
440
441
442
443 public static void fileWriteArray( @Nonnull File file, @Nullable String encoding, @Nullable String... data )
444 throws IOException
445 {
446 Writer writer = null;
447 try
448 {
449 OutputStream out = new FileOutputStream( file );
450 if ( encoding != null )
451 {
452 writer = new OutputStreamWriter( out, encoding );
453 }
454 else
455 {
456 writer = new OutputStreamWriter( out );
457 }
458
459 for ( int i = 0; data != null && i < data.length; i++ )
460 {
461 writer.write( data[i] );
462 if ( i < data.length )
463 {
464 writer.write( "\n" );
465 }
466 }
467 }
468 finally
469 {
470 IOUtil.close( writer );
471 }
472 }
473
474
475
476
477
478
479 public static void fileDelete( @Nonnull String fileName )
480 {
481 File file = new File( fileName );
482
483 deleteLegacyStyle( file );
484 }
485
486
487
488
489
490
491
492
493
494
495
496
497
498 public static String[] getFilesFromExtension( @Nonnull String directory, @Nonnull String... extensions )
499 {
500 List<String> files = new ArrayList<String>();
501
502 File currentDir = new File( directory );
503
504 String[] unknownFiles = currentDir.list();
505
506 if ( unknownFiles == null )
507 {
508 return new String[0];
509 }
510
511 for ( String unknownFile : unknownFiles )
512 {
513 String currentFileName = directory + System.getProperty( "file.separator" ) + unknownFile;
514 File currentFile = new File( currentFileName );
515
516 if ( currentFile.isDirectory() )
517 {
518
519 if ( currentFile.getName().equals( "CVS" ) )
520 {
521 continue;
522 }
523
524
525
526
527 String[] fetchFiles = getFilesFromExtension( currentFileName, extensions );
528 files = blendFilesToList( files, fetchFiles );
529 }
530 else
531 {
532
533
534 String add = currentFile.getAbsolutePath();
535 if ( isValidFile( add, extensions ) )
536 {
537 files.add( add );
538 }
539 }
540 }
541
542
543 String[] foundFiles = new String[files.size()];
544 files.toArray( foundFiles );
545
546 return foundFiles;
547 }
548
549
550
551
552 @Nonnull private static List<String> blendFilesToList( @Nonnull List<String> v, @Nonnull String... files )
553 {
554 Collections.addAll( v, files );
555
556 return v;
557 }
558
559
560
561
562
563
564 private static boolean isValidFile( @Nonnull String file, @Nonnull String... extensions )
565 {
566 String extension = extension( file );
567
568
569
570
571 for ( String extension1 : extensions )
572 {
573 if ( extension1.equals( extension ) )
574 {
575 return true;
576 }
577 }
578
579 return false;
580
581 }
582
583
584
585
586
587
588
589
590 public static void mkdir( @Nonnull String dir )
591 {
592 File file = new File( dir );
593
594 if ( Os.isFamily( Os.FAMILY_WINDOWS ) && !isValidWindowsFileName( file ) )
595 {
596 throw new IllegalArgumentException(
597 "The file (" + dir + ") cannot contain any of the following characters: \n" + StringUtils.join(
598 INVALID_CHARACTERS_FOR_WINDOWS_FILE_NAME, " " ) );
599 }
600
601 if ( !file.exists() )
602 {
603
604 file.mkdirs();
605 }
606 }
607
608
609
610
611
612
613
614
615
616 public static boolean contentEquals( @Nonnull final File file1, @Nonnull final File file2 )
617 throws IOException
618 {
619 final boolean file1Exists = file1.exists();
620 if ( file1Exists != file2.exists() )
621 {
622 return false;
623 }
624
625 if ( !file1Exists )
626 {
627
628 return true;
629 }
630
631 if ( file1.isDirectory() || file2.isDirectory() )
632 {
633
634 return false;
635 }
636
637 InputStream input1 = null;
638 InputStream input2 = null;
639 try
640 {
641 input1 = new FileInputStream( file1 );
642 input2 = new FileInputStream( file2 );
643 return IOUtil.contentEquals( input1, input2 );
644
645 }
646 finally
647 {
648 IOUtil.close( input1 );
649 IOUtil.close( input2 );
650 }
651 }
652
653
654
655
656
657
658
659
660 public @Nullable static File toFile( final @Nullable URL url )
661 {
662 if ( url == null || !url.getProtocol().equalsIgnoreCase( "file" ) )
663 {
664 return null;
665 }
666
667 String filename = url.getFile().replace( '/', File.separatorChar );
668 int pos = -1;
669 while ( ( pos = filename.indexOf( '%', pos + 1 ) ) >= 0 )
670 {
671 if ( pos + 2 < filename.length() )
672 {
673 String hexStr = filename.substring( pos + 1, pos + 3 );
674 char ch = (char) Integer.parseInt( hexStr, 16 );
675 filename = filename.substring( 0, pos ) + ch + filename.substring( pos + 3 );
676 }
677 }
678 return new File( filename );
679 }
680
681
682
683
684
685
686
687
688 @Nonnull public static URL[] toURLs( @Nonnull final File... files )
689 throws IOException
690 {
691 final URL[] urls = new URL[files.length];
692
693 for ( int i = 0; i < urls.length; i++ )
694 {
695
696
697 urls[i] = files[i].toURL();
698 }
699
700 return urls;
701 }
702
703
704
705
706
707
708
709
710
711
712
713
714
715 @Nonnull public static String removeExtension( @Nonnull final String filename )
716 {
717 String ext = extension( filename );
718
719 if ( "".equals( ext ) )
720 {
721 return filename;
722 }
723
724 final int index = filename.lastIndexOf( ext ) - 1;
725 return filename.substring( 0, index );
726 }
727
728
729
730
731
732
733
734
735
736
737
738
739
740 @Nonnull public static String getExtension( @Nonnull final String filename )
741 {
742 return extension( filename );
743 }
744
745
746
747
748
749
750
751
752
753
754
755
756
757 public static void copyFileToDirectory( @Nonnull final File source, @Nonnull final File destinationDirectory )
758 throws IOException
759 {
760 if ( destinationDirectory.exists() && !destinationDirectory.isDirectory() )
761 {
762 throw new IllegalArgumentException( "Destination is not a directory" );
763 }
764
765 copyFile( source, new File( destinationDirectory, source.getName() ) );
766 }
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781 private static void copyFileToDirectoryIfModified( @Nonnull final File source,
782 @Nonnull final File destinationDirectory )
783 throws IOException
784 {
785 if ( destinationDirectory.exists() && !destinationDirectory.isDirectory() )
786 {
787 throw new IllegalArgumentException( "Destination is not a directory" );
788 }
789
790 copyFileIfModified( source, new File( destinationDirectory, source.getName() ) );
791 }
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806 public static void copyFile( @Nonnull final File source, @Nonnull final File destination )
807 throws IOException
808 {
809
810 if ( !source.exists() )
811 {
812 final String message = "File " + source + " does not exist";
813 throw new IOException( message );
814 }
815
816
817 if ( source.getCanonicalPath().equals( destination.getCanonicalPath() ) )
818 {
819
820 return;
821 }
822
823 mkdirsFor( destination );
824
825 doCopyFile( source, destination );
826
827 if ( source.length() != destination.length() )
828 {
829 final String message = "Failed to copy full contents from " + source + " to " + destination;
830 throw new IOException( message );
831 }
832 }
833
834 private static void mkdirsFor( @Nonnull File destination )
835 {
836
837 if ( destination.getParentFile() != null && !destination.getParentFile().exists() )
838 {
839
840 destination.getParentFile().mkdirs();
841 }
842 }
843
844 private static void doCopyFile( @Nonnull File source, @Nonnull File destination )
845 throws IOException
846 {
847 FileInputStream fis = null;
848 FileOutputStream fos = null;
849 FileChannel input = null;
850 FileChannel output = null;
851 try
852 {
853 fis = new FileInputStream( source );
854 fos = new FileOutputStream( destination );
855 input = fis.getChannel();
856 output = fos.getChannel();
857 long size = input.size();
858 long pos = 0;
859 long count;
860 while ( pos < size )
861 {
862 count = size - pos > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : size - pos;
863 pos += output.transferFrom( input, pos, count );
864 }
865 }
866 finally
867 {
868 IOUtil.close( output );
869 IOUtil.close( fos );
870 IOUtil.close( input );
871 IOUtil.close( fis );
872 }
873 }
874
875
876
877
878
879
880
881
882
883
884
885
886
887 private static boolean copyFileIfModified( @Nonnull final File source, @Nonnull final File destination )
888 throws IOException
889 {
890 if ( destination.lastModified() < source.lastModified() )
891 {
892 copyFile( source, destination );
893
894 return true;
895 }
896
897 return false;
898 }
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915 public static void copyURLToFile( @Nonnull final URL source, @Nonnull final File destination )
916 throws IOException
917 {
918 copyStreamToFile( source.openStream(), destination );
919 }
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937 private static void copyStreamToFile( @Nonnull final @WillClose InputStream source,
938 @Nonnull final File destination )
939 throws IOException
940 {
941 FileOutputStream output = null;
942 try
943 {
944
945 if ( destination.getParentFile() != null && !destination.getParentFile().exists() )
946 {
947
948 destination.getParentFile().mkdirs();
949 }
950
951
952 if ( destination.exists() && !destination.canWrite() )
953 {
954 final String message = "Unable to open file " + destination + " for writing.";
955 throw new IOException( message );
956 }
957
958 output = new FileOutputStream( destination );
959 IOUtil.copy( source, output );
960 }
961 finally
962 {
963 IOUtil.close( source );
964 IOUtil.close( output );
965 }
966 }
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986 public static String normalize( final String path )
987 {
988 String normalized = path;
989
990 while ( true )
991 {
992 int index = normalized.indexOf( "//" );
993 if ( index < 0 )
994 {
995 break;
996 }
997 normalized = normalized.substring( 0, index ) + normalized.substring( index + 1 );
998 }
999
1000
1001 while ( true )
1002 {
1003 int index = normalized.indexOf( "/./" );
1004 if ( index < 0 )
1005 {
1006 break;
1007 }
1008 normalized = normalized.substring( 0, index ) + normalized.substring( index + 2 );
1009 }
1010
1011
1012 while ( true )
1013 {
1014 int index = normalized.indexOf( "/../" );
1015 if ( index < 0 )
1016 {
1017 break;
1018 }
1019 if ( index == 0 )
1020 {
1021 return null;
1022 }
1023 int index2 = normalized.lastIndexOf( '/', index - 1 );
1024 normalized = normalized.substring( 0, index2 ) + normalized.substring( index + 3 );
1025 }
1026
1027
1028 return normalized;
1029 }
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041 public static File resolveFile( final File baseFile, String filename )
1042 {
1043 String filenm = filename;
1044 if ( '/' != File.separatorChar )
1045 {
1046 filenm = filename.replace( '/', File.separatorChar );
1047 }
1048
1049 if ( '\\' != File.separatorChar )
1050 {
1051 filenm = filename.replace( '\\', File.separatorChar );
1052 }
1053
1054
1055 if ( filenm.startsWith( File.separator ) || ( Os.isFamily( Os.FAMILY_WINDOWS ) && filenm.indexOf( ":" ) > 0 ) )
1056 {
1057 File file = new File( filenm );
1058
1059 try
1060 {
1061 file = file.getCanonicalFile();
1062 }
1063 catch ( final IOException ioe )
1064 {
1065
1066 }
1067
1068 return file;
1069 }
1070
1071
1072 final char[] chars = filename.toCharArray();
1073 final StringBuilder sb = new StringBuilder();
1074
1075
1076
1077
1078 int start = 0;
1079 if ( '\\' == File.separatorChar )
1080 {
1081 sb.append( filenm.charAt( 0 ) );
1082 start++;
1083 }
1084
1085 for ( int i = start; i < chars.length; i++ )
1086 {
1087 final boolean doubleSeparator = File.separatorChar == chars[i] && File.separatorChar == chars[i - 1];
1088
1089 if ( !doubleSeparator )
1090 {
1091 sb.append( chars[i] );
1092 }
1093 }
1094
1095 filenm = sb.toString();
1096
1097
1098 File file = ( new File( baseFile, filenm ) ).getAbsoluteFile();
1099
1100 try
1101 {
1102 file = file.getCanonicalFile();
1103 }
1104 catch ( final IOException ioe )
1105 {
1106
1107 }
1108
1109 return file;
1110 }
1111
1112
1113
1114
1115
1116
1117
1118 public static void forceDelete( final String file )
1119 throws IOException
1120 {
1121 forceDelete( new File( file ) );
1122 }
1123
1124
1125
1126
1127
1128
1129
1130 public static void forceDelete( @Nonnull final File file )
1131 throws IOException
1132 {
1133 if ( file.isDirectory() )
1134 {
1135 deleteDirectory( file );
1136 }
1137 else
1138 {
1139
1140
1141
1142
1143 boolean filePresent = file.getCanonicalFile().exists();
1144 if ( !deleteFile( file ) && filePresent )
1145 {
1146 final String message = "File " + file + " unable to be deleted.";
1147 throw new IOException( message );
1148 }
1149 }
1150 }
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160 public static void delete( File file )
1161 throws IOException
1162 {
1163 if ( Java7Support.isAtLeastJava7() )
1164 {
1165 Java7Support.delete( file );
1166 }
1167 else
1168 {
1169 if ( !file.delete() )
1170 {
1171 throw new IOException( "Could not delete " + file.getName() );
1172 }
1173 }
1174 }
1175
1176 public static boolean deleteLegacyStyle( File file )
1177 {
1178 if ( Java7Support.isAtLeastJava7() )
1179 {
1180 try
1181 {
1182 Java7Support.delete( file );
1183 return true;
1184 }
1185 catch ( IOException e )
1186 {
1187 return false;
1188 }
1189 }
1190 else
1191 {
1192 return file.delete();
1193 }
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204 private static boolean deleteFile( @Nonnull File file )
1205 throws IOException
1206 {
1207 if ( file.isDirectory() )
1208 {
1209 throw new IOException( "File " + file + " isn't a file." );
1210 }
1211
1212 if ( !deleteLegacyStyle( file ) )
1213 {
1214 if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
1215 {
1216 file = file.getCanonicalFile();
1217 System.gc();
1218 }
1219
1220 try
1221 {
1222 Thread.sleep( 10 );
1223 return deleteLegacyStyle( file );
1224 }
1225 catch ( InterruptedException ex )
1226 {
1227 return deleteLegacyStyle( file );
1228 }
1229 }
1230
1231 return true;
1232 }
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244 public static void forceMkdir( @Nonnull final File file )
1245 throws IOException
1246 {
1247 if ( Os.isFamily( Os.FAMILY_WINDOWS ) && !isValidWindowsFileName( file ) )
1248 {
1249 throw new IllegalArgumentException(
1250 "The file (" + file.getAbsolutePath() + ") cannot contain any of the following characters: \n"
1251 + StringUtils.join( INVALID_CHARACTERS_FOR_WINDOWS_FILE_NAME, " " ) );
1252 }
1253
1254 if ( file.exists() )
1255 {
1256 if ( file.isFile() )
1257 {
1258 final String message =
1259 "File " + file + " exists and is " + "not a directory. Unable to create directory.";
1260 throw new IOException( message );
1261 }
1262 }
1263 else
1264 {
1265 if ( !file.mkdirs() )
1266 {
1267 final String message = "Unable to create directory " + file;
1268 throw new IOException( message );
1269 }
1270 }
1271 }
1272
1273
1274
1275
1276
1277
1278
1279 public static void deleteDirectory( @Nonnull final String directory )
1280 throws IOException
1281 {
1282 deleteDirectory( new File( directory ) );
1283 }
1284
1285
1286
1287
1288
1289
1290
1291 public static void deleteDirectory( @Nonnull final File directory )
1292 throws IOException
1293 {
1294 if ( !directory.exists() )
1295 {
1296 return;
1297 }
1298
1299
1300
1301
1302 if ( deleteLegacyStyle( directory) )
1303 {
1304 return;
1305 }
1306
1307 cleanDirectory( directory );
1308 if ( !deleteLegacyStyle( directory ) )
1309 {
1310 final String message = "Directory " + directory + " unable to be deleted.";
1311 throw new IOException( message );
1312 }
1313 }
1314
1315
1316
1317
1318
1319
1320
1321 public static void cleanDirectory( @Nonnull final File directory )
1322 throws IOException
1323 {
1324 if ( !directory.exists() )
1325 {
1326 final String message = directory + " does not exist";
1327 throw new IllegalArgumentException( message );
1328 }
1329
1330 if ( !directory.isDirectory() )
1331 {
1332 final String message = directory + " is not a directory";
1333 throw new IllegalArgumentException( message );
1334 }
1335
1336 IOException exception = null;
1337
1338 final File[] files = directory.listFiles();
1339
1340 if ( files == null )
1341 {
1342 return;
1343 }
1344
1345 for ( final File file : files )
1346 {
1347 try
1348 {
1349 forceDelete( file );
1350 }
1351 catch ( final IOException ioe )
1352 {
1353 exception = ioe;
1354 }
1355 }
1356
1357 if ( null != exception )
1358 {
1359 throw exception;
1360 }
1361 }
1362
1363
1364
1365
1366
1367
1368
1369 public static long sizeOfDirectory( @Nonnull final String directory )
1370 {
1371 return sizeOfDirectory( new File( directory ) );
1372 }
1373
1374
1375
1376
1377
1378
1379
1380 public static long sizeOfDirectory( @Nonnull final File directory )
1381 {
1382 if ( !directory.exists() )
1383 {
1384 final String message = directory + " does not exist";
1385 throw new IllegalArgumentException( message );
1386 }
1387
1388 if ( !directory.isDirectory() )
1389 {
1390 final String message = directory + " is not a directory";
1391 throw new IllegalArgumentException( message );
1392 }
1393
1394 long size = 0;
1395
1396 final File[] files = directory.listFiles();
1397 if ( files == null )
1398 {
1399 throw new IllegalArgumentException( "Problems reading directory" );
1400 }
1401
1402 for ( final File file : files )
1403 {
1404 if ( file.isDirectory() )
1405 {
1406 size += sizeOfDirectory( file );
1407 }
1408 else
1409 {
1410 size += file.length();
1411 }
1412 }
1413
1414 return size;
1415 }
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428 @Nonnull
1429 public static List<File> getFiles( @Nonnull File directory, @Nullable String includes, @Nullable String excludes )
1430 throws IOException
1431 {
1432 return getFiles( directory, includes, excludes, true );
1433 }
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446 @Nonnull
1447 public static List<File> getFiles( @Nonnull File directory, @Nullable String includes, @Nullable String excludes,
1448 boolean includeBasedir )
1449 throws IOException
1450 {
1451 List<String> fileNames = getFileNames( directory, includes, excludes, includeBasedir );
1452
1453 List<File> files = new ArrayList<File>();
1454
1455 for ( String filename : fileNames )
1456 {
1457 files.add( new File( filename ) );
1458 }
1459
1460 return files;
1461 }
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474 @Nonnull public static List<String> getFileNames( @Nonnull File directory, @Nullable String includes,
1475 @Nullable String excludes, boolean includeBasedir )
1476 throws IOException
1477 {
1478 return getFileNames( directory, includes, excludes, includeBasedir, true );
1479 }
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492 @Nonnull private static List<String> getFileNames( @Nonnull File directory, @Nullable String includes,
1493 @Nullable String excludes, boolean includeBasedir,
1494 boolean isCaseSensitive )
1495 throws IOException
1496 {
1497 return getFileAndDirectoryNames( directory, includes, excludes, includeBasedir, isCaseSensitive, true, false );
1498 }
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511 @Nonnull public static List<String> getDirectoryNames( @Nonnull File directory, @Nullable String includes,
1512 @Nullable String excludes, boolean includeBasedir )
1513 throws IOException
1514 {
1515 return getDirectoryNames( directory, includes, excludes, includeBasedir, true );
1516 }
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529 @Nonnull public static List<String> getDirectoryNames( @Nonnull File directory, @Nullable String includes,
1530 @Nullable String excludes, boolean includeBasedir,
1531 boolean isCaseSensitive )
1532 throws IOException
1533 {
1534 return getFileAndDirectoryNames( directory, includes, excludes, includeBasedir, isCaseSensitive, false, true );
1535 }
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549 @Nonnull public static List<String> getFileAndDirectoryNames( File directory, @Nullable String includes,
1550 @Nullable String excludes, boolean includeBasedir,
1551 boolean isCaseSensitive, boolean getFiles,
1552 boolean getDirectories )
1553 {
1554 DirectoryScanner scanner = new DirectoryScanner();
1555
1556 scanner.setBasedir( directory );
1557
1558 if ( includes != null )
1559 {
1560 scanner.setIncludes( StringUtils.split( includes, "," ) );
1561 }
1562
1563 if ( excludes != null )
1564 {
1565 scanner.setExcludes( StringUtils.split( excludes, "," ) );
1566 }
1567
1568 scanner.setCaseSensitive( isCaseSensitive );
1569
1570 scanner.scan();
1571
1572 List<String> list = new ArrayList<String>();
1573
1574 if ( getFiles )
1575 {
1576 String[] files = scanner.getIncludedFiles();
1577
1578 for ( String file : files )
1579 {
1580 if ( includeBasedir )
1581 {
1582 list.add( directory + FileUtils.FS + file );
1583 }
1584 else
1585 {
1586 list.add( file );
1587 }
1588 }
1589 }
1590
1591 if ( getDirectories )
1592 {
1593 String[] directories = scanner.getIncludedDirectories();
1594
1595 for ( String directory1 : directories )
1596 {
1597 if ( includeBasedir )
1598 {
1599 list.add( directory + FileUtils.FS + directory1 );
1600 }
1601 else
1602 {
1603 list.add( directory1 );
1604 }
1605 }
1606 }
1607
1608 return list;
1609 }
1610
1611
1612
1613
1614
1615
1616
1617
1618 public static void copyDirectory( File sourceDirectory, File destinationDirectory )
1619 throws IOException
1620 {
1621 copyDirectory( sourceDirectory, destinationDirectory, "**", null );
1622 }
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634 public static void copyDirectory( @Nonnull File sourceDirectory, @Nonnull File destinationDirectory,
1635 @Nullable String includes, @Nullable String excludes )
1636 throws IOException
1637 {
1638 if ( !sourceDirectory.exists() )
1639 {
1640 return;
1641 }
1642
1643 List<File> files = getFiles( sourceDirectory, includes, excludes );
1644
1645 for ( File file : files )
1646 {
1647 copyFileToDirectory( file, destinationDirectory );
1648 }
1649 }
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664 public static void copyDirectoryStructure( @Nonnull File sourceDirectory, @Nonnull File destinationDirectory )
1665 throws IOException
1666 {
1667 copyDirectoryStructure( sourceDirectory, destinationDirectory, destinationDirectory, false );
1668 }
1669
1670 private static void copyDirectoryStructure( @Nonnull File sourceDirectory, @Nonnull File destinationDirectory,
1671 File rootDestinationDirectory, boolean onlyModifiedFiles )
1672 throws IOException
1673 {
1674
1675 if ( sourceDirectory == null )
1676 {
1677 throw new IOException( "source directory can't be null." );
1678 }
1679
1680
1681 if ( destinationDirectory == null )
1682 {
1683 throw new IOException( "destination directory can't be null." );
1684 }
1685
1686 if ( sourceDirectory.equals( destinationDirectory ) )
1687 {
1688 throw new IOException( "source and destination are the same directory." );
1689 }
1690
1691 if ( !sourceDirectory.exists() )
1692 {
1693 throw new IOException( "Source directory doesn't exists (" + sourceDirectory.getAbsolutePath() + ")." );
1694 }
1695
1696 File[] files = sourceDirectory.listFiles();
1697
1698 if ( files == null )
1699 {
1700 return;
1701 }
1702
1703 String sourcePath = sourceDirectory.getAbsolutePath();
1704
1705 for ( File file : files )
1706 {
1707 if ( file.equals( rootDestinationDirectory ) )
1708 {
1709
1710 continue;
1711 }
1712
1713 String dest = file.getAbsolutePath();
1714
1715 dest = dest.substring( sourcePath.length() + 1 );
1716
1717 File destination = new File( destinationDirectory, dest );
1718
1719 if ( file.isFile() )
1720 {
1721 destination = destination.getParentFile();
1722
1723 if ( onlyModifiedFiles )
1724 {
1725 copyFileToDirectoryIfModified( file, destination );
1726 }
1727 else
1728 {
1729 copyFileToDirectory( file, destination );
1730 }
1731 }
1732 else if ( file.isDirectory() )
1733 {
1734 if ( !destination.exists() && !destination.mkdirs() )
1735 {
1736 throw new IOException(
1737 "Could not create destination directory '" + destination.getAbsolutePath() + "'." );
1738 }
1739
1740 copyDirectoryStructure( file, destination, rootDestinationDirectory, onlyModifiedFiles );
1741 }
1742 else
1743 {
1744 throw new IOException( "Unknown file type: " + file.getAbsolutePath() );
1745 }
1746 }
1747 }
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762 public static void rename( @Nonnull File from, @Nonnull File to )
1763 throws IOException
1764 {
1765 if ( to.exists() && !deleteLegacyStyle( to ) )
1766 {
1767 throw new IOException( "Failed to delete " + to + " while trying to rename " + from );
1768 }
1769
1770 File parent = to.getParentFile();
1771 if ( parent != null && !parent.exists() && !parent.mkdirs() )
1772 {
1773 throw new IOException( "Failed to create directory " + parent + " while trying to rename " + from );
1774 }
1775
1776 if ( !from.renameTo( to ) )
1777 {
1778 copyFile( from, to );
1779 if ( !deleteLegacyStyle( from ) )
1780 {
1781 throw new IOException( "Failed to delete " + from + " while trying to rename it." );
1782 }
1783 }
1784 }
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809 public static File createTempFile( @Nonnull String prefix, @Nonnull String suffix, @Nullable File parentDir )
1810 {
1811 File result;
1812 String parent = System.getProperty( "java.io.tmpdir" );
1813 if ( parentDir != null )
1814 {
1815 parent = parentDir.getPath();
1816 }
1817 DecimalFormat fmt = new DecimalFormat( "#####" );
1818 SecureRandom secureRandom = new SecureRandom();
1819 long secureInitializer = secureRandom.nextLong();
1820 Random rand = new Random( secureInitializer + Runtime.getRuntime().freeMemory() );
1821 do
1822 {
1823 result = new File( parent, prefix + fmt.format( positiveRandom( rand ) ) + suffix );
1824 }
1825 while ( result.exists() );
1826
1827 return result;
1828 }
1829
1830 private static int positiveRandom( Random rand )
1831 {
1832 int a = rand.nextInt();
1833 while ( a == Integer.MIN_VALUE )
1834 {
1835 a = rand.nextInt();
1836 }
1837 return Math.abs( a );
1838 }
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849 public static void copyFile( @Nonnull File from, @Nonnull File to, @Nullable String encoding,
1850 @Nullable FilterWrapper... wrappers )
1851 throws IOException
1852 {
1853 copyFile( from, to, encoding, wrappers, false );
1854 }
1855
1856 public static abstract class FilterWrapper
1857 {
1858 public abstract Reader getReader( Reader fileReader );
1859 }
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872 public static void copyFile( @Nonnull File from, @Nonnull File to, @Nullable String encoding,
1873 @Nullable FilterWrapper[] wrappers, boolean overwrite )
1874 throws IOException
1875 {
1876 if ( wrappers != null && wrappers.length > 0 )
1877 {
1878
1879 Reader fileReader = null;
1880 Writer fileWriter = null;
1881 try
1882 {
1883 if ( encoding == null || encoding.length() < 1 )
1884 {
1885 fileReader = new BufferedReader( new FileReader( from ) );
1886 fileWriter = new FileWriter( to );
1887 }
1888 else
1889 {
1890 FileInputStream instream = new FileInputStream( from );
1891
1892 FileOutputStream outstream = new FileOutputStream( to );
1893
1894 fileReader = new BufferedReader( new InputStreamReader( instream, encoding ) );
1895
1896 fileWriter = new OutputStreamWriter( outstream, encoding );
1897 }
1898
1899 Reader reader = fileReader;
1900 for ( FilterWrapper wrapper : wrappers )
1901 {
1902 reader = wrapper.getReader( reader );
1903 }
1904
1905 IOUtil.copy( reader, fileWriter );
1906 }
1907 finally
1908 {
1909 IOUtil.close( fileReader );
1910 IOUtil.close( fileWriter );
1911 }
1912 }
1913 else
1914 {
1915 if ( to.lastModified() < from.lastModified() || overwrite )
1916 {
1917 copyFile( from, to );
1918 }
1919 }
1920 }
1921
1922
1923
1924
1925
1926
1927
1928
1929 @Nonnull public static List<String> loadFile( @Nonnull File file )
1930 throws IOException
1931 {
1932 List<String> lines = new ArrayList<String>();
1933
1934 if ( file.exists() )
1935 {
1936 FileReader fileReader = new FileReader( file );
1937 try
1938 {
1939 BufferedReader reader = new BufferedReader( fileReader );
1940
1941 String line = reader.readLine();
1942
1943 while ( line != null )
1944 {
1945 line = line.trim();
1946
1947 if ( !line.startsWith( "#" ) && line.length() != 0 )
1948 {
1949 lines.add( line );
1950 }
1951 line = reader.readLine();
1952 }
1953
1954 reader.close();
1955 }
1956 finally
1957 {
1958 fileReader.close();
1959 }
1960 }
1961
1962 return lines;
1963 }
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974 private static boolean isValidWindowsFileName( @Nonnull File f )
1975 {
1976 if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
1977 {
1978 if ( StringUtils.indexOfAny( f.getName(), INVALID_CHARACTERS_FOR_WINDOWS_FILE_NAME ) != -1 )
1979 {
1980 return false;
1981 }
1982
1983 if ( f.getParentFile() != null )
1984 {
1985 return isValidWindowsFileName( f.getParentFile() );
1986 }
1987 }
1988
1989 return true;
1990 }
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005 public static boolean isSymbolicLink( final File file )
2006 throws IOException
2007 {
2008 if ( Java7Support.isJava7() )
2009 {
2010 return Java7Support.isSymLink( file );
2011 }
2012 return isSymbolicLinkLegacy( file );
2013 }
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023 public static boolean isSymbolicLinkForSure( final File file )
2024 throws IOException
2025 {
2026 return Java7Support.isJava7() && Java7Support.isSymLink( file );
2027 }
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047 static boolean isSymbolicLinkLegacy( final File file )
2048 throws IOException
2049 {
2050 final File canonical = new File( file.getCanonicalPath() );
2051 return !file.getAbsolutePath().equals( canonical.getPath() );
2052 }
2053
2054 }