diff --git a/common/source/java/ch/systemsx/cisd/common/filesystem/FileUtilities.java b/common/source/java/ch/systemsx/cisd/common/filesystem/FileUtilities.java index f75f651442f8e2b9d3c3640da7061d245decc976..1b40978ad4f644cc48c3c6e0b0c362cbd2f8cf56 100644 --- a/common/source/java/ch/systemsx/cisd/common/filesystem/FileUtilities.java +++ b/common/source/java/ch/systemsx/cisd/common/filesystem/FileUtilities.java @@ -50,6 +50,7 @@ import org.apache.commons.io.comparator.LastModifiedFileComparator; import org.apache.commons.lang.CharUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DurationFormatUtils; +import org.apache.log4j.Logger; import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel; import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked; @@ -65,10 +66,14 @@ import ch.systemsx.cisd.common.exceptions.FileExistsException; import ch.systemsx.cisd.common.exceptions.UnknownLastChangedException; import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.common.logging.ISimpleLogger; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.common.logging.LogLevel; import ch.systemsx.cisd.common.parser.Line; import ch.systemsx.cisd.common.parser.filter.AlwaysAcceptLineFilter; import ch.systemsx.cisd.common.parser.filter.ILineFilter; +import ch.systemsx.cisd.common.process.ProcessExecutionHelper; +import ch.systemsx.cisd.common.process.ProcessResult; import ch.systemsx.cisd.common.string.StringUtilities; import ch.systemsx.cisd.common.string.StringUtilities.IUniquenessChecker; @@ -88,6 +93,11 @@ import ch.systemsx.cisd.common.string.StringUtilities.IUniquenessChecker; */ public final class FileUtilities { + private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, + FileUtilities.class); + private static final Logger machineLog = LogFactory.getLogger(LogCategory.MACHINE, + FileUtilities.class); + private FileUtilities() { // Can not be instantiated. @@ -2278,4 +2288,42 @@ public final class FileUtilities return tmpFile.exists(); } + /** + * Returns the size of the specified file or folder. In case of a folder and a Unix-type OS the + * command <tt>du</tt> will be used for better performance in case of huge folders/subfolders. + */ + public static long getSizeOf(File file) + { + if (file == null) + { + throw new IllegalArgumentException("Unspecified file."); + } + if (file.exists() == false) + { + throw new IllegalArgumentException("File does not exists: " + file); + } + if (file.isFile()) + { + return file.length(); + } + if (OSUtilities.isUnix()) + { + ProcessResult result = + ProcessExecutionHelper.run(Arrays.asList("du", "-k", + OSUtilities.isMacOS() ? "-d0" : "--max-depth 0", file.toString()), + operationLog, machineLog); + if (result.isOK()) + { + return Long.parseLong(result.getOutput().get(0).split("\\t")[0]) * 1024; + } + Throwable exception = result.getProcessIOResult().tryGetException(); + if (exception != null) + { + throw CheckedExceptionTunnel.wrapIfNecessary(exception); + } + throw new EnvironmentFailureException("The size of the folder '" + file + + "' couldn't be determined: " + result.getErrorOutput()); + } + return FileUtils.sizeOfDirectory(file); + } } diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FileUtilitiesTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FileUtilitiesTest.java index 9f691e80e07e9a365e536bc8c0b6a86831347462..c3db826b8faeccb4a8cdbd98fd75248e8ac287d7 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FileUtilitiesTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FileUtilitiesTest.java @@ -31,6 +31,7 @@ import org.testng.annotations.Test; import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel; import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; +import ch.systemsx.cisd.base.utilities.OSUtilities; import ch.systemsx.cisd.common.concurrent.IActivityObserver; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; import ch.systemsx.cisd.common.parser.filter.ExcludeEmptyAndCommentLineFilter; @@ -514,4 +515,40 @@ public final class FileUtilitiesTest extends AbstractFileSystemTestCase assertFalse(FileUtilities.isValidFileName("a/b")); } + @Test + public void testGetSizeOf() + { + File testFolder = new File(workingDirectory, "test-folder"); + File subFolder = new File(testFolder, "sub-folder"); + subFolder.mkdirs(); + File file1 = new File(testFolder, "text1.txt"); + FileUtilities.writeToFile(file1, createDummyStringOfSize(4500)); + File file2 = new File(subFolder, "text2.txt"); + FileUtilities.writeToFile(file2, createDummyStringOfSize(300)); + File file3 = new File(subFolder, "text3.txt"); + FileUtilities.writeToFile(file3, createDummyStringOfSize(2900)); + + assertEquals(4500, FileUtilities.getSizeOf(file1)); + assertEquals(300, FileUtilities.getSizeOf(file2)); + assertEquals(2900, FileUtilities.getSizeOf(file3)); + if (OSUtilities.isMacOS()) + { + assertEquals(2 * 4096, FileUtilities.getSizeOf(subFolder)); + assertEquals(4 * 4096, FileUtilities.getSizeOf(testFolder)); + } else if (OSUtilities.isUnix()) + { + assertEquals(3 * 4096, FileUtilities.getSizeOf(subFolder)); + assertEquals(6 * 4096, FileUtilities.getSizeOf(testFolder)); + } + } + + private String createDummyStringOfSize(long size) + { + StringBuilder builder = new StringBuilder(); + for (long i = 0; i < size; i++) + { + builder.append('x'); + } + return builder.toString(); + } }