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