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