Skip to content
Snippets Groups Projects
Commit a54e98fd authored by ribeaudc's avatar ribeaudc
Browse files

add:

- 'IChecksum', 'IChecksumWriter' and 'ChecksumWriter'.
- Unit test for 'IChecksumWriter'.
change:
- '.classpath' which used 'fast-md5' library.

SVN: 2266
parent d5f8ae7f
No related branches found
No related tags found
No related merge requests found
......@@ -13,5 +13,6 @@
<classpathentry kind="lib" path="/libraries/jmock/third-party-libs/hamcrest-library-1.0.jar"/>
<classpathentry kind="lib" path="/libraries/jmock/third-party-libs/objenesis-1.0.jar"/>
<classpathentry kind="lib" path="/libraries/log4j/log4j.jar" sourcepath="/libraries/log4j/src.zip"/>
<classpathentry kind="lib" path="/libraries/fast-md5/fast-md5.jar" sourcepath="/libraries/fast-md5/src.zip"/>
<classpathentry kind="output" path="targets/classes"/>
</classpath>
/*
* Copyright 2007 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.bds;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;
import java.util.Comparator;
import com.twmacinta.util.MD5;
import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
import ch.systemsx.cisd.common.utilities.CompositeComparator;
import ch.systemsx.cisd.common.utilities.FileComparator;
import ch.systemsx.cisd.common.utilities.FileUtilities;
/**
* A default <code>IChecksumWriter</code> implementation.
*
* @author Christian Ribeaud
*/
public final class ChecksumWriter implements IChecksumWriter
{
private final static Comparator<File> BY_TYPE_AND_NAME = createFileComparator();
private static final String LINE_SEPARATOR = "\n";
private static final String COLUMN_SEPARATOR = " ";
private final IChecksum checksumImpl;
/** We use only one instance of <code>StringBuilder</code> and recycle it. */
private final StringBuilder builder;
protected File root;
public ChecksumWriter()
{
this.checksumImpl = new MD5Checksum();
builder = new StringBuilder();
}
@SuppressWarnings("unchecked")
private final static Comparator<File> createFileComparator()
{
return new CompositeComparator<File>(FileComparator.BY_TYPE, FileComparator.BY_NAME);
}
private final static void checkFile(final File file)
{
assert file != null && file.exists();
}
private final void appendToWriter(final File file, final Writer writer)
{
try
{
writer.append(createChecksumLine(file, checksumImpl.getChecksum(file)));
} catch (IOException ex)
{
throw EnvironmentFailureException.fromTemplate(ex, "An I/O exception has been thrown regarding file '%s'.",
file.getAbsolutePath());
}
}
private final void internalWriteChecksum(final File file, final Writer writer)
{
if (file.isFile())
{
appendToWriter(file, writer);
} else if (file.isDirectory())
{
final File[] files = FileUtilities.listFiles(file);
Arrays.sort(files, BY_TYPE_AND_NAME);
for (int i = 0; i < files.length; i++)
{
internalWriteChecksum(files[i], writer);
}
}
}
protected String getColumnSeparator()
{
return COLUMN_SEPARATOR;
}
protected String getLineSeparator()
{
return LINE_SEPARATOR;
}
protected String createChecksumLine(final File file, final String checksum)
{
builder.setLength(0);
builder.append(checksum);
builder.append(getColumnSeparator());
builder.append(FileUtilities.getRelativeFile(root.getAbsolutePath(), file.getAbsolutePath()));
builder.append(getLineSeparator());
return builder.toString();
}
//
// IChecksumHandler
//
public final void writeChecksum(final File file, final Writer writer)
{
checkFile(file);
root = file;
internalWriteChecksum(file, writer);
}
//
// Helper classes
//
/**
* A <code>IChecksum</code> implementation based on <i>MD5</i>.
*
* @author Christian Ribeaud
*/
private final static class MD5Checksum implements IChecksum
{
//
// IChecksum
//
public final String getChecksum(final File file) throws EnvironmentFailureException
{
checkFile(file);
try
{
return MD5.asHex(MD5.getHash(file));
} catch (IOException ex)
{
throw EnvironmentFailureException.fromTemplate(ex,
"An I/O exception has been thrown regarding file '%s'.", file.getAbsolutePath());
}
}
}
}
/*
* Copyright 2007 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.bds;
import java.io.File;
import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
/**
* Implementations know how to compute a <a href="http://en.wikipedia.org/wiki/Checksum">checksum</a> from a file.
*
* @author Christian Ribeaud
*/
public interface IChecksum
{
/**
* Returns the checksum for given <var>file</var>.
*
* @param file could not be <code>null</code> and must exist.
*/
public String getChecksum(final File file) throws EnvironmentFailureException;
}
/*
* Copyright 2007 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.bds;
import java.io.File;
import java.io.Writer;
/**
* Implementations write computed checksums to some specified {@link Writer}.
*
* @author Christian Ribeaud
*/
public interface IChecksumWriter
{
/**
* Appends computed checksum for given <var>file</var> to given <var>writer</var>.
* <p>
* If given <var>file</var> is a directory, then recursively calls this method for each file composing the
* directory.
* </p>
*
* @param file can not be <code>null</code> and must exist.
* @param writer can not be <code>null</code>.
*/
public void writeChecksum(final File file, final Writer writer);
}
\ No newline at end of file
/*
* Copyright 2007 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.bds;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.fail;
import java.io.File;
import java.io.StringWriter;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import ch.systemsx.cisd.common.logging.LogInitializer;
import ch.systemsx.cisd.common.utilities.FileUtilities;
/**
* Test cases for corresponding {@link ChecksumWriter} class.
*
* @author Christian Ribeaud
*/
public class ChecksumWriterTest
{
private static final File UNIT_TEST_ROOT_DIRECTORY = new File("targets" + File.separator + "unit-test-wd");
private static final File WORKING_DIRECTORY =
new File(UNIT_TEST_ROOT_DIRECTORY, ChecksumWriterTest.class.getSimpleName());
private IChecksumWriter checksumWriter = new ChecksumWriter();
@BeforeMethod
public final void setUp()
{
LogInitializer.init();
WORKING_DIRECTORY.mkdirs();
assert WORKING_DIRECTORY.isDirectory();
WORKING_DIRECTORY.deleteOnExit();
}
@Test
public final void testWriteChecksum()
{
FileUtilities.writeToFile(new File(WORKING_DIRECTORY, "file1"), "This is my first file.");
FileUtilities.writeToFile(new File(WORKING_DIRECTORY, "abracadabra"), "This is my second file.");
FileUtilities.writeToFile(new File(WORKING_DIRECTORY, "zoro.txt"), "This is my third file.");
File dir = new File(WORKING_DIRECTORY, "dir");
dir.mkdir();
FileUtilities.writeToFile(new File(dir, "file2"), "This is my fourth file.");
FileUtilities.writeToFile(new File(dir, "escargot.png"), "This is my fifth file.");
FileUtilities.writeToFile(new File(dir, "barbapapa"), "This is my sixth file.");
try
{
checksumWriter.writeChecksum(null, null);
fail("Null value not allowed here.");
} catch (AssertionError e)
{
// Nothing to do here
}
final StringWriter writer = new StringWriter();
try
{
checksumWriter.writeChecksum(new File("choubidou"), writer);
fail("Given file must exist.");
} catch (AssertionError e)
{
// Nothing to do here
}
checksumWriter.writeChecksum(WORKING_DIRECTORY, writer);
assertEquals("31b98e3c4af8d09595dcef2ce8232fbd abracadabra\n"
+ "23b447be20a6ddfe875a8b59ceae83ff file1\n"
+ "0ba14d9315ba1c59449eb2fe1dbcbb61 zoro.txt\n"
+ "23b541115335bbe719c447bb9c942b1a dir/barbapapa\n"
+ "b63f5226ef2d2fc6d38342d90869412c dir/escargot.png\n"
+ "0f782d8d89620f2a5600eba6565f6bfd dir/file2\n", writer.toString());
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment