* under the License.
*/
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.archiva.audit.AuditEvent;
+import org.apache.archiva.audit.AuditListener;
import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.MetadataRepository;
+import org.apache.archiva.metadata.repository.filter.Filter;
+import org.apache.archiva.metadata.repository.filter.IncludesFilter;
import org.apache.archiva.metadata.repository.stats.RepositoryStatisticsManager;
import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.archiva.repository.scanner.RepositoryContentConsumers;
import org.apache.archiva.scheduler.repository.RepositoryArchivaTaskScheduler;
import org.apache.archiva.scheduler.repository.RepositoryTask;
+import org.apache.archiva.stagerepository.merge.RepositoryMerger;
import org.apache.archiva.web.xmlrpc.api.AdministrationService;
import org.apache.archiva.web.xmlrpc.api.beans.ManagedRepository;
import org.apache.archiva.web.xmlrpc.api.beans.RemoteRepository;
import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.RepositoryException;
import org.apache.maven.archiva.repository.RepositoryNotFoundException;
-import org.apache.maven.archiva.security.ArchivaRoleConstants;
-import org.codehaus.plexus.redback.role.RoleManager;
import org.codehaus.plexus.registry.RegistryException;
import org.codehaus.plexus.scheduler.CronExpressionValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
/**
* AdministrationServiceImpl
*
private MetadataRepository metadataRepository;
private RepositoryStatisticsManager repositoryStatisticsManager;
+
+ private RepositoryMerger repositoryMerger;
+
+ private static final String STAGE = "-stage";
+
+ private AuditListener auditListener;
public AdministrationServiceImpl( ArchivaConfiguration archivaConfig, RepositoryContentConsumers repoConsumersUtil,
RepositoryContentFactory repoFactory, MetadataRepository metadataRepository,
RepositoryArchivaTaskScheduler repositoryTaskScheduler,
Collection<RepositoryListener> listeners,
- RepositoryStatisticsManager repositoryStatisticsManager )
+ RepositoryStatisticsManager repositoryStatisticsManager, RepositoryMerger repositoryMerger,
+ AuditListener auditListener )
{
this.archivaConfiguration = archivaConfig;
this.repoConsumersUtil = repoConsumersUtil;
this.listeners = listeners;
this.metadataRepository = metadataRepository;
this.repositoryStatisticsManager = repositoryStatisticsManager;
+ this.repositoryMerger = repositoryMerger;
+ this.auditListener = auditListener;
}
/**
return repo;
}
+ public boolean merge( String repoId, boolean skipConflicts )
+ throws Exception
+ {
+ String stagingId = repoId + STAGE;
+ ManagedRepositoryConfiguration repoConfig;
+ ManagedRepositoryConfiguration stagingConfig;
+
+ Configuration config = archivaConfiguration.getConfiguration();
+ repoConfig = config.findManagedRepositoryById( repoId );
+
+ if( repoConfig != null )
+ {
+ stagingConfig = config.findManagedRepositoryById( stagingId );
+
+ if( stagingConfig != null )
+ {
+ List<ArtifactMetadata> sourceArtifacts = metadataRepository.getArtifacts( stagingId );
+
+ if( repoConfig.isReleases() && !repoConfig.isSnapshots() )
+ {
+ if( skipConflicts )
+ {
+ List<ArtifactMetadata> conflicts = repositoryMerger.getConflictingArtifacts( stagingId, stagingId );
+ sourceArtifacts.removeAll( conflicts );
+ mergeWithOutSnapshots( sourceArtifacts, stagingId, repoId );
+ }
+ else
+ {
+ mergeWithOutSnapshots( sourceArtifacts, stagingId, repoId );
+ }
+ }
+ else
+ {
+ if( skipConflicts )
+ {
+ List<ArtifactMetadata> conflicts = repositoryMerger.getConflictingArtifacts( stagingId, stagingId );
+ sourceArtifacts.removeAll( conflicts );
+ Filter<ArtifactMetadata> artifactsWithOutConflicts = new IncludesFilter<ArtifactMetadata>( sourceArtifacts );
+ repositoryMerger.merge( stagingId, repoId, artifactsWithOutConflicts );
+ }
+ else
+ {
+ repositoryMerger.merge( stagingId, repoId );
+ }
+ }
+ }
+ else
+ {
+ throw new Exception( "Staging Id : " + stagingId + " not found." );
+ }
+ }
+ else
+ {
+ throw new Exception( "Repository Id : " + repoId + " not found." );
+ }
+
+ if ( !repositoryTaskScheduler.isProcessingRepositoryTask( repoId ) )
+ {
+ RepositoryTask task = new RepositoryTask();
+ task.setRepositoryId( repoId );
+
+ repositoryTaskScheduler.queueTask( task );
+ }
+
+ AuditEvent event = createAuditEvent( repoConfig );
+
+ // add event for audit log reports
+ metadataRepository.addMetadataFacet( event.getRepositoryId(), event );
+
+ // log event in archiva audit log
+ auditListener.auditEvent( createAuditEvent( repoConfig ) );
+
+ return true;
+ }
+
+ // todo: setting userid of audit event
+ private AuditEvent createAuditEvent( ManagedRepositoryConfiguration repoConfig )
+ {
+
+ AuditEvent event = new AuditEvent();
+ event.setAction( AuditEvent.MERGE_REPO_REMOTE );
+ event.setRepositoryId( repoConfig.getId() );
+ event.setResource( repoConfig.getLocation() );
+ event.setTimestamp( new Date( ) );
+
+ return event;
+ }
+
+ private void mergeWithOutSnapshots( List<ArtifactMetadata> sourceArtifacts, String sourceRepoId, String repoid )
+ throws Exception
+ {
+ List<ArtifactMetadata> artifactsWithOutSnapshots = new ArrayList<ArtifactMetadata>();
+ for ( ArtifactMetadata metadata : sourceArtifacts )
+ {
+
+ if ( metadata.getProjectVersion().contains( "SNAPSHOT" ) )
+ {
+ artifactsWithOutSnapshots.add( metadata );
+ }
+
+ }
+ sourceArtifacts.removeAll( artifactsWithOutSnapshots );
+
+ Filter<ArtifactMetadata> artifactListWithOutSnapShots = new IncludesFilter<ArtifactMetadata>( sourceArtifacts );
+
+ repositoryMerger.merge( sourceRepoId, repoid, artifactListWithOutSnapShots );
+ }
}
* under the License.
*/
+import org.apache.archiva.audit.AuditEvent;
+import org.apache.archiva.audit.AuditListener;
import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.MetadataRepository;
+import org.apache.archiva.metadata.repository.filter.Filter;
+import org.apache.archiva.metadata.repository.filter.IncludesFilter;
import org.apache.archiva.metadata.repository.stats.RepositoryStatisticsManager;
import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.archiva.repository.scanner.RepositoryContentConsumers;
import org.apache.archiva.scheduler.repository.RepositoryArchivaTaskScheduler;
import org.apache.archiva.scheduler.repository.RepositoryTask;
+import org.apache.archiva.stagerepository.merge.RepositoryMerger;
import org.apache.archiva.web.xmlrpc.api.beans.ManagedRepository;
import org.apache.archiva.web.xmlrpc.api.beans.RemoteRepository;
import org.apache.commons.io.FileUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
/**
private MockControl repositoryStatisticsManagerControl;
private RepositoryStatisticsManager repositoryStatisticsManager;
+
+ private MockControl repositoryMergerControl;
+
+ private RepositoryMerger repositoryMerger;
+
+ private MockControl auditListenerControl;
+
+ private AuditListener auditListener;
+ private static final String STAGE = "-stage";
+
protected void setUp()
throws Exception
{
repositoryStatisticsManagerControl = MockControl.createControl( RepositoryStatisticsManager.class );
repositoryStatisticsManager = (RepositoryStatisticsManager) repositoryStatisticsManagerControl.getMock();
-
+ repositoryMergerControl = MockControl.createControl( RepositoryMerger.class );
+ repositoryMerger = (RepositoryMerger) repositoryMergerControl.getMock();
+
+ auditListenerControl = MockControl.createControl( AuditListener.class );
+ auditListener = ( AuditListener ) auditListenerControl.getMock();
+
service =
new AdministrationServiceImpl( archivaConfig, repoConsumersUtil, repositoryFactory,
metadataRepository, repositoryTaskScheduler,
- Collections.singletonList( listener ), repositoryStatisticsManager );
+ Collections.singletonList( listener ), repositoryStatisticsManager, repositoryMerger, auditListener );
}
/* Tests for repository consumers */
assertRemoteRepo( repos.get( 1 ), remoteRepos.get( 1 ) );
}
+/* Merge method */
+
+ public void testMergeRepositoryWithInvalidRepository()
+ throws Exception
+ {
+ archivaConfigControl.expectAndReturn( archivaConfig.getConfiguration(), config );
+ configControl.expectAndReturn( config.findManagedRepositoryById( "invalid" ), null );
+
+ archivaConfigControl.replay();
+ configControl.replay();
+
+ try
+ {
+ service.merge( "invalid", true );
+ }
+ catch( Exception e )
+ {
+ assertEquals( "Repository Id : invalid not found.", e.getMessage() );
+ }
+
+ archivaConfigControl.verify();
+ configControl.verify();
+ }
+
+ public void testMergeWithNoStagingRepository()
+ throws Exception
+ {
+ archivaConfigControl.expectAndReturn( archivaConfig.getConfiguration(), config );
+ configControl.expectAndReturn( config.findManagedRepositoryById( "repo" ), createManagedRepo( "repo", "default", "repo", true, false ) );
+ configControl.expectAndReturn( config.findManagedRepositoryById( "repo-stage" ), null );
+
+ archivaConfigControl.replay();
+ configControl.replay();
+
+ try
+ {
+ service.merge( "repo", true );
+ }
+ catch( Exception e )
+ {
+ assertEquals( "Staging Id : repo-stage not found.", e.getMessage() );
+ }
+
+ archivaConfigControl.verify();
+ configControl.verify();
+ }
+
+ public void testMergeRepositoriesAndScan( )
+ throws Exception
+ {
+ List<ArtifactMetadata> sources = new ArrayList<ArtifactMetadata>();
+
+ ArtifactMetadata artifact = new ArtifactMetadata();
+ artifact.setId( "artifact" );
+ artifact.setFileLastModified( System.currentTimeMillis() );
+
+ sources.add( artifact );
+
+ ManagedRepositoryConfiguration merge = createManagedRepo( "merge", "default", "merge", true, true );
+ merge.setLocation( "target/test-repository/merge" );
+ ManagedRepositoryConfiguration staging = createStagingRepo( merge );
+
+ RepositoryTask task = new RepositoryTask();
+ task.setScanAll( true );
+
+ archivaConfigControl.expectAndReturn( archivaConfig.getConfiguration(), config );
+ configControl.expectAndReturn( config.findManagedRepositoryById( "merge" ), merge );
+ configControl.expectAndReturn( config.findManagedRepositoryById( "merge-stage" ), staging );
+
+ metadataRepositoryControl.expectAndReturn( metadataRepository.getArtifacts( staging.getId() ), sources );
+ repositoryMergerControl.expectAndDefaultReturn( repositoryMerger.getConflictingArtifacts( staging.getId(), merge.getId() ), sources );
+ repositoryMerger.merge( staging.getId(), merge.getId() );
+ repositoryMergerControl.setMatcher( MockControl.ALWAYS_MATCHER );
+ repositoryMergerControl.setVoidCallable();
+ repositoryTaskSchedulerControl.expectAndReturn( repositoryTaskScheduler.isProcessingRepositoryTask( "merge" ), false);
+
+ // scanning after merge
+ repositoryTaskScheduler.queueTask( task );
+ repositoryTaskSchedulerControl.setMatcher( MockControl.ALWAYS_MATCHER );
+ repositoryTaskSchedulerControl.setVoidCallable();
+
+ // audit logs
+ metadataRepository.addMetadataFacet( merge.getId() ,createAuditEvent( merge) );
+ metadataRepositoryControl.setMatcher( MockControl.ALWAYS_MATCHER );
+ metadataRepositoryControl.setVoidCallable();
+
+ archivaConfigControl.replay();
+ metadataRepositoryControl.replay();
+ configControl.replay();
+ repositoryMergerControl.replay();
+ repositoryTaskSchedulerControl.replay();
+
+ boolean a = service.merge( "merge", false );
+ assertTrue( a );
+
+ archivaConfigControl.verify();
+ configControl.verify();
+ configControl.verify();
+ metadataRepositoryControl.verify();
+ repositoryMergerControl.verify();
+ repositoryTaskSchedulerControl.verify();
+ }
+
+ public void testMergeRepositoriesWithConflictsAndScan( )
+ throws Exception
+ {
+ List<ArtifactMetadata> sources = new ArrayList<ArtifactMetadata>();
+ ArtifactMetadata one = new ArtifactMetadata();
+ one.setId( "one" );
+ one.setVersion( "1.0" );
+
+ ArtifactMetadata two = new ArtifactMetadata();
+ two.setId( "two" );
+ two.setVersion( "1.0-SNAPSHOT" );
+
+ sources.add( one );
+ sources.add( two );
+
+ List<ArtifactMetadata> conflicts = new ArrayList<ArtifactMetadata>();
+ conflicts.add( one );
+
+ sources.removeAll( conflicts );
+
+ Filter<ArtifactMetadata> artifactsWithOutConflicts = new IncludesFilter<ArtifactMetadata>( sources );
+
+ RepositoryTask task = new RepositoryTask();
+ task.setScanAll( true );
+
+ ManagedRepositoryConfiguration repo = createManagedRepo( "repo", "default", "repo", true, true );
+ repo.setLocation( "target/test-repository/one" );
+ ManagedRepositoryConfiguration staging = createStagingRepo( repo );
+
+ archivaConfigControl.expectAndReturn( archivaConfig.getConfiguration(), config );
+ configControl.expectAndReturn( config.findManagedRepositoryById( "repo" ), repo );
+ configControl.expectAndReturn( config.findManagedRepositoryById( "repo-stage" ), staging );
+
+ metadataRepositoryControl.expectAndReturn( metadataRepository.getArtifacts( staging.getId() ), sources );
+ repositoryMergerControl.expectAndDefaultReturn( repositoryMerger.getConflictingArtifacts( staging.getId(), repo.getId() ), conflicts );
+ repositoryMerger.merge( staging.getId(), repo.getId(), artifactsWithOutConflicts );
+ repositoryMergerControl.setMatcher( MockControl.ALWAYS_MATCHER );
+ repositoryMergerControl.setVoidCallable();
+ repositoryTaskSchedulerControl.expectAndReturn( repositoryTaskScheduler.isProcessingRepositoryTask( "repo" ), false);
+ repositoryTaskScheduler.queueTask( task );
+ repositoryTaskSchedulerControl.setMatcher( MockControl.ALWAYS_MATCHER );
+ repositoryTaskSchedulerControl.setVoidCallable();
+
+ // audit logs
+ metadataRepository.addMetadataFacet( repo.getId() ,createAuditEvent( repo ) );
+ metadataRepositoryControl.setMatcher( MockControl.ALWAYS_MATCHER );
+ metadataRepositoryControl.setVoidCallable();
+
+ archivaConfigControl.replay();
+ metadataRepositoryControl.replay();
+ configControl.replay();
+ repositoryMergerControl.replay();
+ repositoryTaskSchedulerControl.replay();
+
+ boolean a = service.merge( "repo", true );
+ assertTrue( a );
+
+ archivaConfigControl.verify();
+ configControl.verify();
+ configControl.verify();
+ metadataRepositoryControl.verify();
+ repositoryMergerControl.verify();
+ repositoryTaskSchedulerControl.verify();
+ }
+
/* private methods */
private void assertRemoteRepo( RemoteRepository remoteRepo, RemoteRepositoryConfiguration expectedRepoConfig )
return repoConfig;
}
+ private ManagedRepositoryConfiguration createStagingRepo( ManagedRepositoryConfiguration repoConfig )
+ {
+ ManagedRepositoryConfiguration stagingRepo = new ManagedRepositoryConfiguration();
+ stagingRepo.setId( repoConfig.getId() + STAGE );
+ stagingRepo.setLayout( repoConfig.getLayout() );
+ stagingRepo.setName( repoConfig + STAGE );
+ stagingRepo.setReleases( repoConfig.isReleases() );
+ stagingRepo.setSnapshots( repoConfig.isSnapshots() );
+ stagingRepo.setLocation( repoConfig.getLocation() );
+
+ return stagingRepo;
+ }
+
+ private AuditEvent createAuditEvent( ManagedRepositoryConfiguration repoConfig )
+ {
+ AuditEvent auditEvent = new AuditEvent();
+
+ auditEvent.setAction( AuditEvent.MERGE_REPO_REMOTE );
+ auditEvent.setRepositoryId( repoConfig.getId() );
+ auditEvent.setResource( repoConfig.getLocation() );
+ auditEvent.setTimestamp( new Date( ) );
+
+ return auditEvent;
+ }
+
private void recordRepoConsumers()
{
List<KnownRepositoryContentConsumer> availableKnownConsumers = new ArrayList<KnownRepositoryContentConsumer>();