1 package net.sf.jpkgmk.util;
2
3 import java.io.BufferedInputStream;
4 import java.io.BufferedOutputStream;
5 import java.io.File;
6 import java.io.FileFilter;
7 import java.io.FileInputStream;
8 import java.io.FileOutputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.InputStreamReader;
12 import java.io.OutputStream;
13 import java.io.OutputStreamWriter;
14 import java.io.Reader;
15 import java.io.Writer;
16 import java.net.URL;
17 import java.nio.channels.FileChannel;
18 import java.nio.charset.Charset;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.zip.GZIPOutputStream;
24
25 import net.sf.jpkgmk.PackageException;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.tools.tar.TarEntry;
30 import org.apache.tools.tar.TarOutputStream;
31
32
33
34
35
36
37
38 public class FileUtil
39 {
40 private static int BUFFER_SIZE = 1024;
41
42
43
44 private static int BLOCK_SIZE = 512;
45 private static Log log = LogFactory.getLog(FileUtil.class);
46 public static String UNIX_FILE_SEPARATOR = "/";
47
48 private FileUtil()
49 {
50 }
51
52
53
54
55
56
57 public static File createGzip(File inputFile)
58 {
59 File targetFile = new File(inputFile.getParentFile(), inputFile.getName() + ".gz");
60 if(targetFile.exists()) {
61 log.warn("The target file '" + targetFile + "' already exists. Will overwrite");
62 }
63
64 FileInputStream in = null;
65 GZIPOutputStream out = null;
66 try {
67 int read = 0;
68 byte[] data = new byte[BUFFER_SIZE];
69 in = new FileInputStream(inputFile);
70
71 out = new GZIPOutputStream(new FileOutputStream(targetFile));
72
73 while((read = in.read(data, 0, BUFFER_SIZE)) != -1) {
74 out.write(data, 0, read);
75 }
76 in.close();
77 out.close();
78
79 boolean deleteSuccess = inputFile.delete();
80 if(!deleteSuccess) {
81 log.warn("Could not delete file '" + inputFile + "'");
82 }
83 log.info("Successfully created gzip file '" + targetFile + "'.");
84 }
85 catch(Exception e) {
86 log.error("Exception while creating GZIP.", e);
87 }
88 finally {
89 StreamUtil.tryCloseStream(in);
90 StreamUtil.tryCloseStream(out);
91 }
92 return targetFile;
93 }
94
95
96
97
98
99
100
101
102 public static void createTar(File directoryToPack, File targetTarFile) throws IOException
103 {
104 if (directoryToPack == null) {
105 throw new NullPointerException(
106 "The parameter 'directoryToPack' must not be null");
107 }
108
109 if (targetTarFile == null) {
110 throw new NullPointerException(
111 "The parameter 'targetTarFile' must not be null");
112 }
113
114 if(!directoryToPack.exists() || !directoryToPack.isDirectory()) {
115 throw new IllegalArgumentException("The target file '" + directoryToPack + "' does not exist or is not a directory.");
116 }
117 if(targetTarFile.exists()) {
118 log.warn("The target file '" + targetTarFile + "' already exists. Will overwrite");
119 }
120
121 log.debug("Creating tar from all files in directory '" + directoryToPack + "'");
122
123 byte buffer[] = new byte[BUFFER_SIZE];
124
125 FileOutputStream targetOutput = new FileOutputStream(targetTarFile);
126 TarOutputStream targetOutputTar = new TarOutputStream(targetOutput);
127
128
129
130 try {
131 List<File> fileList = collectFiles(directoryToPack);
132
133 for(Iterator<File> iter=fileList.iterator(); iter.hasNext(); ) {
134 File file=iter.next();
135 if (file == null || !file.exists() || file.isDirectory()) {
136 log.info("The file '" + file + "' is ignored - is a directory or non-existent");
137 continue;
138 }
139
140 if(file.equals(targetTarFile)) {
141 log.debug("Skipping file: '" + file + "' - is the tar file itself");
142 continue;
143 }
144
145 log.debug("Adding to archive: file='" + file + "', archive='" + targetTarFile + "'");
146
147
148 String filePathInTar = getFilePathInTar(file, directoryToPack);
149 log.debug("File path in tar: '" + filePathInTar + "' (file=" + file + ")");
150
151 TarEntry tarAdd = new TarEntry(file);
152 tarAdd.setModTime(file.lastModified());
153 tarAdd.setName(filePathInTar);
154 targetOutputTar.putNextEntry(tarAdd);
155
156 if(file.isFile()) {
157 FileInputStream in = new FileInputStream(file);
158 try {
159 while (true) {
160 int nRead = in.read(buffer, 0, buffer.length);
161 if (nRead <= 0)
162 break;
163 targetOutputTar.write(buffer, 0, nRead);
164 }
165 }
166 finally {
167 StreamUtil.tryCloseStream(in);
168 }
169 }
170 targetOutputTar.closeEntry();
171 }
172 }
173 finally {
174 StreamUtil.tryCloseStream(targetOutputTar);
175 StreamUtil.tryCloseStream(targetOutput);
176 }
177 log.info("Tar Archive created successfully '" + targetTarFile + "'");
178 }
179
180
181
182
183
184
185
186
187 static String getFilePathInTar(File file, File directoryToPack)
188 {
189 String result = file.getName();
190 for(File currentFileToCheck=file.getParentFile(); !currentFileToCheck.equals(directoryToPack); currentFileToCheck=currentFileToCheck.getParentFile()) {
191 result = currentFileToCheck.getName() + "/" + result;
192 }
193 return result;
194 }
195
196 private static List<File> collectFiles(File directoryToPack) {
197 List<File> result = new ArrayList<File>();
198 File[] fileList = directoryToPack.listFiles();
199 for (int i = 0; i < fileList.length; i++) {
200 File file = fileList[i];
201 result.add(file);
202 if(file.isDirectory()) {
203
204 List<File> children = collectFiles(file);
205 result.addAll(children);
206 }
207 }
208 return result;
209 }
210
211 public static void deleteRecursively(File fileOrDirectory) {
212 if(fileOrDirectory.isFile()) {
213 boolean success = fileOrDirectory.delete();
214 if(!success) {
215 throw new RuntimeException("The file '" + fileOrDirectory.getAbsolutePath() + "' could not be deleted");
216 }
217 else {
218 log.debug("Successfully deleted file '" + fileOrDirectory + "'.");
219 }
220 }
221 else {
222
223 File[] children = fileOrDirectory.listFiles();
224 for (int i = 0; i < children.length; i++) {
225 File file = children[i];
226 deleteRecursively(file);
227 }
228
229 boolean success = fileOrDirectory.delete();
230 if(!success) {
231 throw new RuntimeException("The directory '" + fileOrDirectory.getAbsolutePath() + "' could not be deleted");
232 }
233 else {
234 log.debug("Successfully deleted directory '" + fileOrDirectory + "'.");
235 }
236 }
237 }
238
239
240 public static void writeFile(File target, String content) throws IOException
241 {
242 Charset charset = Charset.defaultCharset();
243 log.info("Using default character set " + charset + " for writing data to file " + target);
244 writeFile(target, content, charset);
245 }
246
247 public static void writeFile(File target, String content, Charset charset) throws IOException
248 {
249 OutputStream output = new BufferedOutputStream(new FileOutputStream(target));
250 try {
251 Writer writer = new OutputStreamWriter(output, charset);
252 writer.write(content);
253 writer.flush();
254 }
255 finally {
256 StreamUtil.tryCloseStream(output);
257 }
258 }
259
260 public static String readFile(File file) throws IOException
261 {
262 if (file == null) {
263 throw new NullPointerException(
264 "The parameter 'file' must not be null");
265 }
266
267 InputStream input = new BufferedInputStream(new FileInputStream(file));
268 try {
269 return FileUtil.readString(input);
270 }
271 finally {
272 StreamUtil.tryCloseStream(input);
273 }
274 }
275
276 public static String readString(URL file) throws IOException
277 {
278 if (file == null) {
279 throw new NullPointerException(
280 "The parameter 'file' must not be null");
281 }
282
283 InputStream input = file.openStream();
284 try {
285 return FileUtil.readString(input);
286 }
287 finally {
288 StreamUtil.tryCloseStream(input);
289 }
290 }
291
292
293
294
295
296
297
298
299
300 public static String readString(InputStream input) throws IOException {
301 log.info("Using default character set " + Charset.defaultCharset() + " for reading input stream...");
302 return FileUtil.readString(input, Charset.defaultCharset());
303 }
304
305
306
307
308
309
310
311
312 public static String readString(InputStream input, Charset charset) throws IOException {
313 Reader reader = new InputStreamReader(input, charset);
314
315 StringBuffer sb = new StringBuffer();
316 int character = -1;
317 while((character=reader.read()) != -1) {
318 sb.append((char)character);
319 }
320 return sb.toString();
321 }
322
323
324 public static boolean isSubdir(File subDirToCheck, File basedir) {
325 if(subDirToCheck.equals(basedir)) {
326 return true;
327 }
328 else {
329 File parentOfSubdir = subDirToCheck.getParentFile();
330 if(parentOfSubdir == null) {
331
332 return false;
333 }
334 else {
335
336 return FileUtil.isSubdir(parentOfSubdir, basedir);
337 }
338 }
339 }
340
341
342
343
344
345
346
347 public static String buildPath(File fileOrDir, String pathSeparator) {
348
349 if(File.separator.equals(pathSeparator)) {
350 log.info("The file separator is already a '" + File.separator + "'. Nothing to do here.");
351 return fileOrDir.getPath();
352 }
353
354 String result = "";
355 for(File current=fileOrDir; current!=null; current=current.getParentFile() ) {
356 String name = current.getName();
357 if(current.isFile()) {
358 result = name;
359 }
360 else {
361 result = name + pathSeparator + result;
362 }
363 }
364 return result;
365 }
366
367
368
369
370
371
372
373 public static List<File> getFiles(File destDir, FileFilter filter) {
374 List<File> resultList = new ArrayList<File>();
375 File[] children = null;
376 if(filter != null) {
377 children = destDir.listFiles();
378 }
379 else {
380 children = destDir.listFiles(filter);
381 }
382 if(children != null) {
383 resultList.addAll(Arrays.asList(children));
384
385
386 for (int i = 0; i < children.length; i++) {
387
388 List<File> childrenResult = getFiles(children[i], filter);
389 resultList.addAll(childrenResult);
390 }
391 }
392
393 return resultList;
394 }
395
396
397
398
399
400
401
402
403 public static void copyFiles(File sourceDir, File targetDir, FileFilter fileFilter) throws IOException
404 {
405 if(!sourceDir.isDirectory()) {
406 throw new IllegalArgumentException("The given sourceDir '" + sourceDir + "' must be a directory.");
407 }
408 if(!sourceDir.isDirectory()) {
409 throw new IllegalArgumentException("The given targetDir '" + targetDir + "' must be a directory.");
410 }
411
412 File[] sourceChildren = null;
413 if(fileFilter == null) {
414 sourceChildren = sourceDir.listFiles();
415 }
416 else {
417 sourceChildren = sourceDir.listFiles(fileFilter);
418 }
419
420
421 if(sourceChildren == null) {
422 return;
423 }
424
425 List<File> fileList = Arrays.asList(sourceChildren);
426 for(Iterator<File> iter=fileList.iterator(); iter.hasNext(); ) {
427 File file = iter.next();
428 File fileInTarget = new File(targetDir, file.getName());
429 if(file.isDirectory()) {
430 boolean dirSuccess = fileInTarget.mkdir();
431 if(!dirSuccess) {
432 throw new RuntimeException("Could not create directory " + targetDir + ". Aborting");
433 }
434
435 log.debug("Created directory '" + fileInTarget + "'");
436
437 FileUtil.copyFiles(file, fileInTarget, fileFilter);
438 }
439 else {
440
441 FileUtil.copyFile(file, fileInTarget);
442 }
443 }
444 }
445
446
447
448
449
450
451
452 public static void copyFile(File sourceFile, File destFile)
453 throws IOException
454 {
455 log.info("Copying file '" + sourceFile + "' to '" + destFile + "'");
456
457 if(!sourceFile.isFile()) {
458 throw new IllegalArgumentException("The sourceFile '" + sourceFile + "' does not exist or is not a normal file.");
459 }
460
461 if (!destFile.exists()) {
462 destFile.createNewFile();
463 }
464
465 FileChannel source = null;
466 FileChannel destination = null;
467 try {
468 source = new FileInputStream(sourceFile).getChannel();
469 destination = new FileOutputStream(destFile).getChannel();
470 long numberOfBytes = destination.transferFrom(source, 0, source.size());
471 log.debug("Transferred " + numberOfBytes + " bytes from '" + sourceFile + "' to '" + destFile + "'.");
472 } finally {
473 if (source != null) {
474 source.close();
475 }
476 if (destination != null) {
477 destination.close();
478 }
479 }
480 }
481
482 public static void createDir(File dir, boolean failOnError) {
483 boolean success = dir.mkdir();
484 if(success) {
485 log.debug("Successfully created directory '" + dir + "'");
486 }
487 else {
488 if(dir.isDirectory()) {
489 log.debug("The directory '" + dir + "' already exists. Nothing to do.");
490 return;
491 }
492
493 String errorMessage = "Could not create '" + dir + "'.";
494
495 File parent = dir.getParentFile();
496 if(!parent.exists()) {
497 errorMessage += " The parent directory '" + parent + "' does not exist.";
498 }
499
500
501 if(failOnError) {
502 throw new IllegalStateException(errorMessage);
503 }
504 else {
505 log.warn(errorMessage);
506 }
507 }
508
509 }
510
511
512
513
514
515
516
517 public static boolean isRelocatable(String path) {
518 if(path == null) {
519 return false;
520 }
521 return !path.startsWith(UNIX_FILE_SEPARATOR);
522 }
523
524
525
526
527
528
529
530 public static int countFilesAndDirectories(File directory) {
531 return countFiles(directory, true);
532 }
533
534
535
536
537
538
539 public static int countFiles(File directory) {
540 return countFiles(directory, false);
541 }
542
543
544
545
546
547
548
549 public static int countFiles(File directory, boolean countDirectories) {
550 if(directory==null) {
551 throw new NullPointerException("The parameter 'directory' must not be null");
552 }
553 int count = 0;
554 File[] files = directory.listFiles();
555 if(files != null) {
556 for (int i = 0; i < files.length; i++) {
557 if(files[i].isDirectory()) {
558 if(countDirectories)
559 count++;
560 count += countFiles(files[i]);
561 }
562 else {
563 count++;
564 }
565 }
566 }
567 return count;
568 }
569
570
571
572
573
574
575 public static Long getBlockCount(File basedir) {
576 if(basedir == null) {
577 throw new NullPointerException("The parameter 'basedir' must not be null.");
578 }
579 long fileSize = FileUtil.getSize(basedir);
580 long blockCount = fileSize / BLOCK_SIZE + (fileSize % BLOCK_SIZE>0 ? 1 : 0);
581 return new Long(blockCount);
582 }
583
584
585
586
587
588
589 public static long getSize(File basedir) {
590 if(basedir == null) {
591 throw new NullPointerException("The parameter 'basedir' must not be null.");
592 }
593 File[] children = basedir.listFiles();
594 long overallSize = 0;
595 for (int i = 0; i < children.length; i++) {
596 File currentFile = children[i];
597 if(currentFile.isFile()) {
598 overallSize += currentFile.length();
599 }
600 else {
601
602 long childSize = getSize(currentFile);
603 overallSize += childSize;
604 }
605 }
606 return overallSize;
607 }
608
609
610
611
612
613
614
615 public static void assertContainsFiles(File dirToCheck, File[] expectedFiles) {
616 File[] actualFiles = dirToCheck.listFiles();
617 List<File> actualFileList = Arrays.asList(actualFiles);
618 List<File> expectedFileList = Arrays.asList(expectedFiles);
619 boolean equal = actualFileList.equals(expectedFileList);
620 if(!equal) {
621 throw new PackageException("The files in directory '" + dirToCheck + "' are not equal to the given array of files. " +
622 "Expected: " + expectedFileList + ", Actual: " + actualFileList);
623 }
624 }
625
626 }