implements RepositoryConverter
{
/**
- * @plexus.requirement role-hint="sha1"
+ * {@link List}<{@link Digester}>
+ *
+ * @plexus.requirement role="org.codehaus.plexus.digest.Digester"
*/
- private Digester sha1Digester;
-
- /**
- * @plexus.requirement role-hint="md5"
- */
- private Digester md5Digester;
+ private List digesters;
/**
* @plexus.requirement
mappingWriter.write( writer, metadata );
- transaction.createFile( writer.toString(), file );
+ transaction.createFile( writer.toString(), file, digesters );
}
catch ( IOException e )
{
}
if ( force || !matching )
{
- transaction.createFile( contents, targetFile );
+ transaction.createFile( contents, targetFile, digesters );
}
}
catch ( IOException e )
MavenXpp3Writer Xpp3Writer = new MavenXpp3Writer();
Xpp3Writer.write( writer, v4Model );
- transaction.createFile( writer.toString(), targetFile );
+ transaction.createFile( writer.toString(), targetFile, digesters );
List warnings = translator.getWarnings();
MavenXpp3Writer pomWriter = new MavenXpp3Writer();
pomWriter.write( strWriter, pom );
- transaction.createFile( strWriter.toString(), pomFile );
+ transaction.createFile( strWriter.toString(), pomFile, digesters );
}
private String getI18NString( String key, String arg0 )
private boolean testChecksums( Artifact artifact, File file, ReportingDatabase reporter )
throws IOException
{
-
- boolean result =
- verifyChecksum( file, file.getName() + ".md5", md5Digester, reporter, artifact, "failure.incorrect.md5" );
- result = result && verifyChecksum( file, file.getName() + ".sha1", sha1Digester, reporter, artifact,
- "failure.incorrect.sha1" );
+ boolean result = true;
+ Iterator it = digesters.iterator();
+ while ( it.hasNext() )
+ {
+ Digester digester = (Digester) it.next();
+ result &= verifyChecksum( file, file.getName() + "." + getDigesterFileExtension( digester ), digester,
+ reporter, artifact, "failure.incorrect." + getDigesterFileExtension( digester ) );
+ }
return result;
}
+ /**
+ * File extension for checksums
+ * TODO should be moved to plexus-digester ?
+ */
+ private String getDigesterFileExtension( Digester digester )
+ {
+ return digester.getAlgorithm().toLowerCase().replaceAll( "-", "" );
+ }
+
private boolean verifyChecksum( File file, String fileName, Digester digester, ReportingDatabase reporter,
Artifact artifact, String key )
throws IOException
{
if ( testChecksums( artifact, sourceFile, reporter ) )
{
- transaction.copyFile( sourceFile, targetFile );
+ transaction.copyFile( sourceFile, targetFile, digesters );
}
else
{
* under the License.
*/
-import org.apache.commons.io.FileUtils;
-
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+import org.codehaus.plexus.digest.Digester;
+import org.codehaus.plexus.digest.DigesterException;
+import org.codehaus.plexus.logging.AbstractLogEnabled;
/**
* Abstract class for the TransactionEvents
*
* @author Edwin Punzalan
+ * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
+ * @version $Id$
*/
public abstract class AbstractTransactionEvent
+ extends AbstractLogEnabled
implements TransactionEvent
{
- private File backup;
+ private Map backups = new HashMap();;
+
+ private List createdDirs = new ArrayList();
+
+ private List createdFiles = new ArrayList();
+
+ /** {@link List}<{@link Digester}> */
+ private List digesters;
- private List createdDirs;
+ protected AbstractTransactionEvent()
+ {
+ this( new ArrayList( 0 ) );
+ }
+
+ protected AbstractTransactionEvent( List digesters )
+ {
+ this.digesters = digesters;
+ }
+
+ protected List getDigesters()
+ {
+ return digesters;
+ }
/**
* Method that creates a directory as well as all the parent directories needed
parent = parent.getParentFile();
}
- createdDirs = new ArrayList();
-
while ( !createDirs.isEmpty() )
{
File directory = (File) createDirs.remove( createDirs.size() - 1 );
}
}
+ protected void revertFilesCreated()
+ throws IOException
+ {
+ Iterator it = createdFiles.iterator();
+ while ( it.hasNext() )
+ {
+ File file = (File) it.next();
+ file.delete();
+ it.remove();
+ }
+ }
+
protected void createBackup( File file )
throws IOException
{
if ( file.exists() && file.isFile() )
{
- backup = File.createTempFile( "temp-", ".backup" );
+ File backup = File.createTempFile( "temp-", ".backup" );
FileUtils.copyFile( file, backup );
backup.deleteOnExit();
+
+ backups.put( file, backup );
+ }
+ }
+
+ protected void restoreBackups()
+ throws IOException
+ {
+ Iterator it = backups.entrySet().iterator();
+ while ( it.hasNext() )
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ FileUtils.copyFile( (File) entry.getValue(), (File) entry.getKey() );
}
}
protected void restoreBackup( File file )
throws IOException
{
+ File backup = (File) backups.get( file );
if ( backup != null )
{
FileUtils.copyFile( backup, file );
}
}
+
+ /**
+ * Create checksums of file using all digesters defined at construction time.
+ *
+ * @param file
+ * @param force whether existing checksums should be overwritten or not
+ * @throws IOException
+ */
+ protected void createChecksums( File file, boolean force )
+ throws IOException
+ {
+ Iterator it = getDigesters().iterator();
+ while ( it.hasNext() )
+ {
+ Digester digester = (Digester) it.next();
+ File checksumFile = new File( file.getAbsolutePath() + "." + getDigesterFileExtension( digester ) );
+ if ( checksumFile.exists() )
+ {
+ if ( !force )
+ {
+ continue;
+ }
+ createBackup( checksumFile );
+ }
+ else
+ {
+ createdFiles.add( checksumFile );
+ }
+ try
+ {
+ FileUtils.writeStringToFile( checksumFile, digester.calc( file ), null );
+ }
+ catch ( DigesterException e )
+ {
+ // the Digester API just wraps IOException and should be fixed
+ throw (IOException) e.getCause();
+ }
+ }
+ }
+
+ /**
+ * File extension for checksums
+ * TODO should be moved to plexus-digester ?
+ */
+ protected String getDigesterFileExtension( Digester digester )
+ {
+ return digester.getAlgorithm().toLowerCase().replaceAll( "-", "" );
+ }
+
}
* under the License.
*/
-import org.apache.commons.io.FileUtils;
-
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.codehaus.plexus.digest.Digester;
/**
* Event to copy a file.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
+ * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
+ * @version $Id$
*/
public class CopyFileEvent
extends AbstractTransactionEvent
private final File destination;
+ /**
+ * Creates a copy file event with no digesters
+ *
+ * @deprecated use other constructors
+ *
+ * @param source
+ * @param destination
+ */
public CopyFileEvent( File source, File destination )
{
+ this( source, destination, new ArrayList( 0 ) );
+ }
+
+ /**
+ *
+ * @param source
+ * @param destination
+ * @param digesters {@link List}<{@link Digester}> digesters to use for checksumming
+ */
+ public CopyFileEvent( File source, File destination, List digesters )
+ {
+ super( digesters );
this.source = source;
this.destination = destination;
}
mkDirs( destination.getParentFile() );
FileUtils.copyFile( source, destination );
+
+ createChecksums( destination, true );
+ copyChecksums();
+
+ copyChecksum( "asc" );
+ }
+
+ /**
+ * Copy checksums of source file with all digesters if exist
+ *
+ * @throws IOException
+ */
+ private void copyChecksums()
+ throws IOException
+ {
+ Iterator it = getDigesters().iterator();
+ while ( it.hasNext() )
+ {
+ Digester digester = (Digester) it.next();
+ copyChecksum( getDigesterFileExtension( digester ) );
+ }
+ }
+
+ /**
+ * Copy checksum of source file with extension provided if exists
+ *
+ * @param extension
+ * @return whether the checksum exists or not
+ * @throws IOException
+ */
+ private boolean copyChecksum( String extension )
+ throws IOException
+ {
+ File checksumSource = new File( source.getAbsolutePath() + "." + extension );
+ if ( checksumSource.exists() )
+ {
+ File checksumDestination = new File( destination.getAbsolutePath() + "." + extension );
+ FileUtils.copyFile( checksumSource, checksumDestination );
+ return true;
+ }
+ return false;
}
public void rollback()
{
destination.delete();
+ revertFilesCreated();
+
revertMkDirs();
- restoreBackup( destination );
+ restoreBackups();
}
}
* under the License.
*/
-import org.apache.commons.io.FileUtils;
-
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.codehaus.plexus.digest.Digester;
/**
* Event for creating a file from a string content.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
+ * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
+ * @version $Id$
*/
public class CreateFileEvent
extends AbstractTransactionEvent
private final String content;
+ /**
+ * Creates a create file event with no digesters
+ *
+ * @deprecated use other constructors
+ *
+ * @param content
+ * @param destination
+ */
public CreateFileEvent( String content, File destination )
{
+ this( content, destination, new ArrayList( 0 ) );
+ }
+
+ /**
+ *
+ * @param content
+ * @param destination
+ * @param digesters {@link List}<{@link Digester}> digesters to use for checksumming
+ */
+ public CreateFileEvent( String content, File destination, List digesters )
+ {
+ super( digesters );
this.content = content;
this.destination = destination;
}
}
FileUtils.writeStringToFile( destination, content, null );
+
+ createChecksums( destination, true );
}
public void rollback()
{
destination.delete();
+ revertFilesCreated();
+
revertMkDirs();
- restoreBackup( destination );
+ restoreBackups();
}
}
*/
import org.apache.maven.archiva.converter.RepositoryConversionException;
+import org.codehaus.plexus.digest.Digester;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
}
}
+ /**
+ * @deprecated use {@link #copyFile(File, File, List)}
+ * @param source
+ * @param destination
+ */
public void copyFile( File source, File destination )
{
- events.add( new CopyFileEvent( source, destination ) );
+ copyFile( source, destination, Collections.EMPTY_LIST );
}
+ /**
+ *
+ * @param source
+ * @param destination
+ * @param digesters {@link List}<{@link Digester}> digesters to use for checksumming
+ */
+ public void copyFile( File source, File destination, List digesters )
+ {
+ events.add( new CopyFileEvent( source, destination, digesters ) );
+ }
+
+ /**
+ * @deprecated use {@link #createFile(String, File, List)}
+ * @param content
+ * @param destination
+ */
public void createFile( String content, File destination )
{
- events.add( new CreateFileEvent( content, destination ) );
+ createFile( content, destination, Collections.EMPTY_LIST );
+ }
+
+ /**
+ *
+ * @param content
+ * @param destination
+ * @param digesters {@link List}<{@link Digester}> digesters to use for checksumming
+ */
+ public void createFile( String content, File destination, List digesters )
+ {
+ events.add( new CreateFileEvent( content, destination, digesters ) );
}
}
--- /dev/null
+package org.apache.maven.archiva.converter.transaction;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.codehaus.plexus.PlexusTestCase;
+import org.codehaus.plexus.digest.Digester;
+
+/**
+ *
+ * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
+ * @version $Id$
+ */
+public abstract class AbstractFileEventTest
+ extends PlexusTestCase
+{
+ protected List digesters;
+
+ public void setUp()
+ throws Exception
+ {
+ super.setUp();
+
+ digesters = getContainer().lookupList( Digester.class.getName() );
+ }
+
+ protected void assertChecksumExists( File file, String algorithm )
+ {
+ assertChecksum( file, algorithm, true );
+ }
+
+ protected void assertChecksumDoesNotExist( File file, String algorithm )
+ {
+ assertChecksum( file, algorithm, false );
+ }
+
+ private void assertChecksum( File file, String algorithm, boolean exist )
+ {
+ String msg = exist ? "exists" : "does not exist";
+ File checksumFile = new File( file.getPath() + "." + algorithm );
+ assertEquals( "Test file " + algorithm + " checksum " + msg, exist, checksumFile.exists() );
+ }
+
+ protected void assertChecksumCommit( File file )
+ throws IOException
+ {
+ assertChecksumExists( file, "md5" );
+ assertChecksumExists( file, "sha1" );
+ }
+
+ protected void assertChecksumRollback( File file )
+ throws IOException
+ {
+ assertChecksumDoesNotExist( file, "md5" );
+ assertChecksumDoesNotExist( file, "sha1" );
+ }
+}
\ No newline at end of file
* under the License.
*/
+import java.io.File;
+import java.io.IOException;
+
import org.apache.commons.io.FileUtils;
import org.codehaus.plexus.PlexusTestCase;
-import java.io.File;
-
/**
* @author Edwin Punzalan
*/
public class CopyFileEventTest
- extends PlexusTestCase
+ extends AbstractFileEventTest
{
private File testDir = new File( PlexusTestCase.getBasedir(), "target/transaction-tests/copy-file" );
private File testSource = new File( PlexusTestCase.getBasedir(), "target/transaction-tests/test-file.txt" );
+ private File testDestChecksum;
+
+ private String source, oldChecksum;
+
public void setUp()
throws Exception
{
testSource.createNewFile();
FileUtils.writeStringToFile( testSource, "source contents", null );
+
+ testDestChecksum = new File( testDest.getPath() + ".sha1" );
+
+ testDestChecksum.getParentFile().mkdirs();
+
+ testDestChecksum.createNewFile();
+
+ FileUtils.writeStringToFile( testDestChecksum, "this is the checksum", null );
+
+ assertTrue( "Test if the source exists", testSource.exists() );
+
+ assertTrue( "Test if the destination checksum exists", testDestChecksum.exists() );
+
+ source = FileUtils.readFileToString( testSource, null );
+
+ oldChecksum = FileUtils.readFileToString( testDestChecksum, null );
}
public void testCopyCommitRollback()
throws Exception
{
- assertTrue( "Test if the source exists", testSource.exists() );
-
- String source = FileUtils.readFileToString( testSource, null );
-
- CopyFileEvent event = new CopyFileEvent( testSource, testDest );
+ CopyFileEvent event = new CopyFileEvent( testSource, testDest, digesters );
assertFalse( "Test that the destination is not yet created", testDest.exists() );
assertTrue( "Test that the destination is created", testDest.exists() );
+ assertChecksumCommit( testDest );
+
String target = FileUtils.readFileToString( testDest, null );
assertTrue( "Test that the destination contents are copied correctly", source.equals( target ) );
event.rollback();
assertFalse( "Test that the destination file has been deleted", testDest.exists() );
+
+ assertChecksumRollback( testDest );
}
public void testCopyCommitRollbackWithBackup()
throws Exception
{
- assertTrue( "Test if the source exists", testSource.exists() );
-
- String source = FileUtils.readFileToString( testSource, null );
-
testDest.getParentFile().mkdirs();
testDest.createNewFile();
assertTrue( "Test that the destination exists", testDest.exists() );
- CopyFileEvent event = new CopyFileEvent( testSource, testDest );
+ CopyFileEvent event = new CopyFileEvent( testSource, testDest, digesters );
String target = FileUtils.readFileToString( testDest, null );
assertTrue( "Test that the destination contents are copied correctly", source.equals( target ) );
+ assertChecksumCommit( testDest );
+
event.rollback();
target = FileUtils.readFileToString( testDest, null );
assertTrue( "Test the destination file contents have been restored", target.equals( "overwritten contents" ) );
+
+ assertChecksumRollback( testDest );
}
public void testCreateRollbackCommit()
throws Exception
{
- assertTrue( "Test if the source exists", testSource.exists() );
-
- String source = FileUtils.readFileToString( testSource, null );
-
- CopyFileEvent event = new CopyFileEvent( testSource, testDest );
+ CopyFileEvent event = new CopyFileEvent( testSource, testDest, digesters );
assertFalse( "Test that the destination is not yet created", testDest.exists() );
assertTrue( "Test that the destination is created", testDest.exists() );
+ assertChecksumCommit( testDest );
+
String target = FileUtils.readFileToString( testDest, null );
assertTrue( "Test that the destination contents are copied correctly", source.equals( target ) );
FileUtils.deleteDirectory( new File( PlexusTestCase.getBasedir(), "target/transaction-tests" ) );
}
+
+ protected void assertChecksumCommit( File file )
+ throws IOException
+ {
+ super.assertChecksumCommit( file );
+
+ String target = FileUtils.readFileToString( testDestChecksum, null );
+
+ assertFalse( "Test that the destination checksum contents are created correctly", oldChecksum.equals( target ) );
+ }
+
+ protected void assertChecksumRollback( File file )
+ throws IOException
+ {
+ assertChecksumDoesNotExist( file, "md5" );
+ assertChecksumExists( file, "sha1" );
+
+ String target = FileUtils.readFileToString( testDestChecksum, null );
+
+ assertEquals( "Test that the destination checksum contents are reverted correctly", oldChecksum, target );
+ }
}
* under the License.
*/
+import java.io.File;
+
import org.apache.commons.io.FileUtils;
import org.codehaus.plexus.PlexusTestCase;
-import java.io.File;
-
/**
* @author Edwin Punzalan
*/
public class CreateFileEventTest
- extends PlexusTestCase
+ extends AbstractFileEventTest
{
private File testDir = new File( PlexusTestCase.getBasedir(), "target/transaction-tests/create-file" );
{
File testFile = new File( testDir, "test-file.txt" );
- CreateFileEvent event = new CreateFileEvent( "file contents", testFile );
+ CreateFileEvent event = new CreateFileEvent( "file contents", testFile, digesters );
assertFalse( "Test file is not yet created", testFile.exists() );
event.commit();
- assertTrue( "Test file is not yet created", testFile.exists() );
+ assertTrue( "Test file has been created", testFile.exists() );
+
+ assertChecksumCommit( testFile );
event.rollback();
assertFalse( "Test file is has been deleted after rollback", testFile.exists() );
+
+ assertChecksumRollback( testFile );
+
assertFalse( "Test file parent directories has been rolledback too", testDir.exists() );
assertTrue( "target directory still exists", new File( PlexusTestCase.getBasedir(), "target" ).exists() );
}
FileUtils.writeStringToFile( testFile, "original contents", null );
- CreateFileEvent event = new CreateFileEvent( "modified contents", testFile );
+ CreateFileEvent event = new CreateFileEvent( "modified contents", testFile, digesters );
String contents = FileUtils.readFileToString( testFile, null );
assertEquals( "Test contents have not changed", "modified contents", contents );
+ assertChecksumCommit( testFile );
+
event.rollback();
contents = FileUtils.readFileToString( testFile, null );
assertEquals( "Test contents have not changed", "original contents", contents );
+
+ assertChecksumRollback( testFile );
}
public void testCreateRollbackCommit()
{
File testFile = new File( testDir, "test-file.txt" );
- CreateFileEvent event = new CreateFileEvent( "file contents", testFile );
+ CreateFileEvent event = new CreateFileEvent( "file contents", testFile, digesters );
assertFalse( "Test file is not yet created", testFile.exists() );
event.commit();
assertTrue( "Test file is not yet created", testFile.exists() );
+
+ assertChecksumCommit( testFile );
}
protected void tearDown()
<requirements>
<requirement>
<role>org.codehaus.plexus.digest.Digester</role>
- <role-hint>sha1</role-hint>
- <field-name>sha1Digester</field-name>
- </requirement>
- <requirement>
- <role>org.codehaus.plexus.digest.Digester</role>
- <role-hint>md5</role-hint>
- <field-name>md5Digester</field-name>
+ <field-name>digesters</field-name>
</requirement>
<requirement>
<role>org.apache.maven.artifact.factory.ArtifactFactory</role>
<requirements>
<requirement>
<role>org.codehaus.plexus.digest.Digester</role>
- <role-hint>sha1</role-hint>
- <field-name>sha1Digester</field-name>
- </requirement>
- <requirement>
- <role>org.codehaus.plexus.digest.Digester</role>
- <role-hint>md5</role-hint>
- <field-name>md5Digester</field-name>
+ <field-name>digesters</field-name>
</requirement>
<requirement>
<role>org.apache.maven.artifact.factory.ArtifactFactory</role>