diff options
author | Martin Stockhammer <martin_s@apache.org> | 2021-01-27 20:16:26 +0100 |
---|---|---|
committer | Martin Stockhammer <martin_s@apache.org> | 2021-01-27 20:16:26 +0100 |
commit | b32d75a85b4f5805d6d251ea2237f838087aa2bf (patch) | |
tree | 162037148959d4bddb68ef7a7aa22ea89a69759f /archiva-modules/archiva-base | |
parent | 7eef53d7c5145de75ecb6734169bacb53b02f5a0 (diff) | |
download | archiva-b32d75a85b4f5805d6d251ea2237f838087aa2bf.tar.gz archiva-b32d75a85b4f5805d6d251ea2237f838087aa2bf.zip |
Adding task admin implementation
Diffstat (limited to 'archiva-modules/archiva-base')
15 files changed, 1166 insertions, 7 deletions
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/AbstractArtifactConsumerTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/AbstractArtifactConsumerTest.java index d6b116e3a..0ff779ffe 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/AbstractArtifactConsumerTest.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/AbstractArtifactConsumerTest.java @@ -25,8 +25,10 @@ import org.apache.archiva.configuration.FileType; import org.apache.archiva.configuration.FileTypes; import org.apache.archiva.consumers.KnownRepositoryContentConsumer; import org.apache.archiva.consumers.functors.ConsumerWantsFilePredicate; +import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.apache.commons.lang3.StringUtils; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -37,8 +39,7 @@ import javax.inject.Inject; import java.nio.file.Path; import java.nio.file.Paths; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.*; @RunWith( ArchivaSpringJUnit4ClassRunner.class ) @ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml", "classpath:/spring-context.xml" } ) @@ -54,6 +55,8 @@ public abstract class AbstractArtifactConsumerTest @Inject ArchivaConfiguration archivaConfiguration; + ArchivaRepositoryRegistry repositoryRegistry; + @Before public void setUp() @@ -68,6 +71,14 @@ public abstract class AbstractArtifactConsumerTest archivaConfiguration.getConfiguration().getArchivaRuntimeConfiguration().addChecksumType("SHA256"); repoLocation = Paths.get( "target/test-" + getName() + "/test-repo" ); + + repositoryRegistry = applicationContext.getBean( "repositoryRegistry", ArchivaRepositoryRegistry.class ); + assertNotNull( repositoryRegistry ); + } + + @After + public void destroy() { + repositoryRegistry.destroy(); } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java index cfcd19efe..2f906a586 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java @@ -24,6 +24,8 @@ import org.apache.archiva.metadata.repository.MetadataRepository; import org.apache.archiva.metadata.repository.RepositorySession; import org.apache.archiva.metadata.repository.RepositorySessionFactory; import org.apache.archiva.repository.ManagedRepositoryContent; +import org.apache.archiva.repository.RepositoryRegistry; +import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; import org.apache.archiva.repository.maven.metadata.storage.Maven2RepositoryPathTranslator; import org.apache.archiva.repository.base.BasicManagedRepository; import org.apache.archiva.repository.ReleaseScheme; @@ -53,8 +55,7 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import static org.mockito.Mockito.mock; /** @@ -108,6 +109,8 @@ public abstract class AbstractRepositoryPurgeTest protected MetadataRepository metadataRepository; + protected ArchivaRepositoryRegistry repositoryRegistry; + @Inject protected ApplicationContext applicationContext; @@ -127,6 +130,8 @@ public abstract class AbstractRepositoryPurgeTest repositorySession = sessionControl.createMock( RepositorySession.class ); metadataRepository = mock( MetadataRepository.class ); sessionFactory = sessionFactoryControl.createMock( RepositorySessionFactory.class ); + repositoryRegistry = applicationContext.getBean( "repositoryRegistry", ArchivaRepositoryRegistry.class ); + assertNotNull( repositoryRegistry ); EasyMock.expect( repositorySession.getRepository() ).andStubReturn( metadataRepository ); EasyMock.expect( sessionFactory.createSession( ) ).andStubReturn( repositorySession ); @@ -138,6 +143,7 @@ public abstract class AbstractRepositoryPurgeTest { config = null; repo = null; + repositoryRegistry.destroy(); } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/spring-context-cleanup-released-snapshots.xml b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/spring-context-cleanup-released-snapshots.xml index 2f646583c..ee3d8e022 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/spring-context-cleanup-released-snapshots.xml +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/spring-context-cleanup-released-snapshots.xml @@ -32,7 +32,7 @@ </bean> <alias name="archivaConfiguration#cleanup-released-snapshots" alias="archivaConfiguration"/> <alias name="archivaConfiguration#cleanup-released-snapshots" alias="archivaConfiguration#default"/> - <context:component-scan base-package="org.apache.archiva.configuration,org.apache.archiva.repository.content.maven2,org.apache.archiva.indexer.maven"/> + <context:component-scan base-package="org.apache.archiva.configuration,org.apache.archiva.repository.content.base,org.apache.archiva.indexer.maven"/> <alias name="repositoryContentFactory#cleanup-released-snapshots" alias="repositoryContentFactory#default" /> diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/admin/ArchivaAdministration.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/admin/ArchivaAdministration.java index 7037f4957..beda0b97a 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/admin/ArchivaAdministration.java +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/admin/ArchivaAdministration.java @@ -29,6 +29,7 @@ import org.apache.archiva.admin.model.beans.UiConfiguration; import java.util.List; /** + * Base administration interface for Archiva. Provides methods for managing archiva base tasks. * @author Olivier Lamy * @since 1.4-M1 */ diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/admin/RepositoryTaskAdministration.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/admin/RepositoryTaskAdministration.java new file mode 100644 index 000000000..0375f2e73 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/admin/RepositoryTaskAdministration.java @@ -0,0 +1,115 @@ +package org.apache.archiva.admin.model.admin; +/* + * 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 org.apache.archiva.admin.model.RepositoryAdminException; +import org.apache.archiva.admin.model.beans.RepositoryTaskInfo; +import org.apache.archiva.admin.model.beans.ScanStatus; +import org.springframework.util.StopWatch; + +import java.util.List; + +/** + * Interface for managing repository scan tasks. + * + * @author Martin Stockhammer <martin_s@apache.org> + * @since 3.0 + */ +public interface RepositoryTaskAdministration +{ + /** + * Schedules a full repository scan for the given repository. Metadata and Index are updated. + * All files are scanned, even if they were not modified since the last scan. + * + * @param repositoryId the repository identifier + * @throws RepositoryAdminException if it was not possible to schedule the scan + */ + void scheduleFullScan( String repositoryId ) throws RepositoryAdminException; + + /** + * Schedules a scan that rebuilds the fulltext index of the repository. + * + * @param repositoryId the repository identifier + * @throws RepositoryAdminException if it was not possible to schedule the index scan + */ + void scheduleIndexFullScan( String repositoryId ) throws RepositoryAdminException; + + /** + * Schedules a scan that rebuilds the fulltext index of the repository. + * + * @param repositoryId the repository identifier + * @param relativePath the path to the file to add to the index + * @throws RepositoryAdminException if it was not possible to schedule the index scan + */ + void scheduleIndexScan( String repositoryId, String relativePath ) throws RepositoryAdminException; + + /** + * Schedules a scan that rebuilds metadata of the repository + * + * @param repositoryId the repository identifier + * @throws RepositoryAdminException if it was not possible to schedule the index scan + */ + void scheduleMetadataFullScan( String repositoryId ) throws RepositoryAdminException; + + /** + * Schedules a scan that rebuilds metadata of the repository but only for updated files. + * + * @param repositoryId the repository identifier + * @throws RepositoryAdminException if it was not possible to schedule the index scan + */ + void scheduleMetadataUpdateScan( String repositoryId ) throws RepositoryAdminException; + + /** + * Returns information about currently running scans for the given repository. + * + * @return the status information + * @param repositoryId the repository identifier + * @throws RepositoryAdminException if there was an error retrieving the scan status + */ + ScanStatus getCurrentScanStatus(String repositoryId) throws RepositoryAdminException; + + + /** + * Returns information about currently running scans for all repositories. + * + * @return the status information + * @throws RepositoryAdminException if there was an error retrieving the scan status + */ + ScanStatus getCurrentScanStatus() throws RepositoryAdminException; + + /** + * Cancels the tasks either running or queued for the given repository. + * @param repositoryId the repository identifier + * @return a list of canceled tasks. + */ + List<RepositoryTaskInfo> cancelTasks(String repositoryId) throws RepositoryAdminException; + + /** + * Cancels the metadata scan tasks either running or queued for the given repository. + * @param repositoryId the repository identifier + * @return a list of canceled tasks. + */ + List<RepositoryTaskInfo> cancelScanTasks(String repositoryId) throws RepositoryAdminException; + + /** + * Cancels the indexing tasks either running or queued for the given repository. + * @param repositoryId the repository identifier + * @return a list of canceled tasks. + */ + List<RepositoryTaskInfo> cancelIndexTasks(String repositoryId) throws RepositoryAdminException; +} diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/IndexingTask.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/IndexingTask.java new file mode 100644 index 000000000..8b39c201c --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/IndexingTask.java @@ -0,0 +1,87 @@ +package org.apache.archiva.admin.model.beans; +/* + * 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.Serializable; + +/** + * Information about index update tasks running on a repository. + * + * @author Martin Stockhammer <martin_s@apache.org> + */ +public class IndexingTask extends RepositoryTaskInfo implements Serializable +{ + private static final long serialVersionUID = -1947200162602613310L; + /** + * <code>true</code>, if this task is just updating the existing index. + */ + private boolean updateOnly; + + public boolean isUpdateOnly( ) + { + return updateOnly; + } + + public void setUpdateOnly( boolean updateOnly ) + { + this.updateOnly = updateOnly; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + IndexingTask that = (IndexingTask) o; + + if ( isFullScan( ) != that.fullScan ) return false; + if ( updateOnly != that.updateOnly ) return false; + if ( isRunning( ) != that.isRunning( ) ) return false; + if ( getMaxExecutionTimeMs( ) != that.getMaxExecutionTimeMs( ) ) return false; + if ( !getRepositoryId( ).equals( that.getRepositoryId( ) ) ) return false; + return getResource( ).equals( that.getResource( ) ); + } + + @Override + public int hashCode( ) + { + int result = getRepositoryId( ).hashCode( ); + result = 31 * result + ( isFullScan( ) ? 1 : 0 ); + result = 31 * result + ( updateOnly ? 1 : 0 ); + result = 31 * result + getResource( ).hashCode( ); + result = 31 * result + ( isRunning( ) ? 1 : 0 ); + result = 31 * result + (int) ( getMaxExecutionTimeMs( ) ^ ( getMaxExecutionTimeMs( ) >>> 32 ) ); + return result; + } + + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "IndexingTask{" ); + sb.append( "repositoryId='" ).append( getRepositoryId( ) ).append( '\'' ); + sb.append( ", fullRepository=" ).append( isFullScan( ) ); + sb.append( ", updateOnly=" ).append( updateOnly ); + sb.append( ", resource='" ).append( getResource( ) ).append( '\'' ); + sb.append( ", running=" ).append( isRunning( ) ); + sb.append( ", maxExecutionTimeMs=" ).append( getMaxExecutionTimeMs( ) ); + sb.append( '}' ); + return sb.toString( ); + } + +} diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/MetadataScanTask.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/MetadataScanTask.java new file mode 100644 index 000000000..02ab7ee8c --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/MetadataScanTask.java @@ -0,0 +1,84 @@ +package org.apache.archiva.admin.model.beans; +/* + * 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.Serializable; + +/** + * @author Martin Stockhammer <martin_s@apache.org> + */ +public class MetadataScanTask extends RepositoryTaskInfo implements Serializable +{ + private static final long serialVersionUID = -681163357370848098L; + /** + * <code>true</code> if related artifacts are updated too. + */ + private boolean updateRelatedArtifacts; + + public boolean isUpdateRelatedArtifacts( ) + { + return updateRelatedArtifacts; + } + + public void setUpdateRelatedArtifacts( boolean updateRelatedArtifacts ) + { + this.updateRelatedArtifacts = updateRelatedArtifacts; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + MetadataScanTask scanTask = (MetadataScanTask) o; + + if ( updateRelatedArtifacts != scanTask.updateRelatedArtifacts ) return false; + if ( fullScan != scanTask.fullScan ) return false; + if ( running != scanTask.running ) return false; + if ( maxExecutionTimeMs != scanTask.maxExecutionTimeMs ) return false; + if ( !repositoryId.equals( scanTask.repositoryId ) ) return false; + return resource.equals( scanTask.resource ); + } + + @Override + public int hashCode( ) + { + int result = repositoryId.hashCode( ); + result = 31 * result + ( updateRelatedArtifacts ? 1 : 0 ); + result = 31 * result + ( fullScan ? 1 : 0 ); + result = 31 * result + ( running ? 1 : 0 ); + result = 31 * result + resource.hashCode( ); + result = 31 * result + (int) ( maxExecutionTimeMs ^ ( maxExecutionTimeMs >>> 32 ) ); + return result; + } + + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "ScanTask{" ); + sb.append( "repositoryId='" ).append( repositoryId ).append( '\'' ); + sb.append( ", updateRelatedArtifacts=" ).append( updateRelatedArtifacts ); + sb.append( ", fullRepository=" ).append( fullScan ); + sb.append( ", running=" ).append( running ); + sb.append( ", resource='" ).append( resource ).append( '\'' ); + sb.append( ", maxExecutionTimeMs=" ).append( maxExecutionTimeMs ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RepositoryTaskInfo.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RepositoryTaskInfo.java new file mode 100644 index 000000000..9a0a838bd --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RepositoryTaskInfo.java @@ -0,0 +1,121 @@ +package org.apache.archiva.admin.model.beans; +/* + * 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.time.OffsetDateTime; + +/** + * @author Martin Stockhammer <martin_s@apache.org> + */ +public class RepositoryTaskInfo +{ + /** + * The repository identifier + */ + protected String repositoryId = ""; + /** + * <code>true</code>, if all files are scanned. <code>false</code>, if only updated files are scanned + */ + protected boolean fullScan; + /** + * The scanned resource, if this is not a full repository scan + */ + protected String resource = ""; + /** + * Running status of the task. + */ + protected boolean running = false; + /** + * The maximum execution time set for this task. + */ + protected long maxExecutionTimeMs = 0; + /** + * The time when the status check was built + */ + OffsetDateTime checkTime; + + public RepositoryTaskInfo( ) + { + this.checkTime = OffsetDateTime.now( ); + } + + public RepositoryTaskInfo( OffsetDateTime checkTime ) + { + this.checkTime = checkTime; + } + + public String getRepositoryId( ) + { + return repositoryId; + } + + public void setRepositoryId( String repositoryId ) + { + this.repositoryId = repositoryId==null?"":repositoryId; + } + + public boolean isFullScan( ) + { + return fullScan; + } + + public void setFullScan( boolean fullScan ) + { + this.fullScan = fullScan; + } + + public String getResource( ) + { + return resource; + } + + public void setResource( String resource ) + { + this.resource = resource == null ? "" : resource; + } + + public boolean isRunning( ) + { + return running; + } + + public void setRunning( boolean running ) + { + this.running = running; + } + + public long getMaxExecutionTimeMs( ) + { + return maxExecutionTimeMs; + } + + public void setMaxExecutionTimeMs( long maxExecutionTimeMs ) + { + this.maxExecutionTimeMs = maxExecutionTimeMs; + } + + public OffsetDateTime getCheckTime( ) + { + return checkTime; + } + + public void setCheckTime( OffsetDateTime checkTime ) + { + this.checkTime = checkTime; + } +} diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/ScanStatus.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/ScanStatus.java new file mode 100644 index 000000000..50dc46e57 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/ScanStatus.java @@ -0,0 +1,85 @@ +package org.apache.archiva.admin.model.beans; +/* + * 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.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * Information about running and queued repository scans. + * + * @author Martin Stockhammer <martin_s@apache.org> + */ +public class ScanStatus implements Serializable +{ + private List<IndexingTask> indexingQueue = new ArrayList<>( ); + private List<MetadataScanTask> scanQueue = new ArrayList<>( ); + + public ScanStatus( ) + { + } + + public boolean isMetadataScanRunning( ) + { + return scanQueue.size( ) > 0 && scanQueue.get(0).isRunning(); + } + + public int getMetadataScanQueueSize() { + int size= scanQueue.size( ); + if (size>0) { + return size-1; + } else { + return 0; + } + } + + public boolean isIndexScanRunning( ) + { + return indexingQueue.size()>0 && indexingQueue.get(0).isRunning(); + } + + public int getIndexScanQueueSize() { + int size = indexingQueue.size(); + if (size>0) { + return size-1; + } else { + return 0; + } + } + + public List<IndexingTask> getIndexingQueue( ) + { + return indexingQueue; + } + + public void setIndexingQueue( List<IndexingTask> indexingQueue ) + { + this.indexingQueue = new ArrayList<>( indexingQueue ); + } + + public List<MetadataScanTask> getScanQueue( ) + { + return scanQueue; + } + + public void setScanQueue( List<MetadataScanTask> scanQueue ) + { + this.scanQueue = new ArrayList<>( scanQueue ); + } +} diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/resources/org/apache/archiva/admin/model/error/AdminErrors.properties b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/resources/org/apache/archiva/admin/model/error/AdminErrors.properties index 4addc0aef..82056a09f 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/resources/org/apache/archiva/admin/model/error/AdminErrors.properties +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/resources/org/apache/archiva/admin/model/error/AdminErrors.properties @@ -26,3 +26,7 @@ repository_group.repository.not_found=The member repository with id "{0}" does n repository_group.registry.add_error=The registry could not add the repository "{0}": {1} repository_group.registry.update_error=The registry could not update the repository "{0}": {1} repository_group.not_editable=The repository group "{0}" is not editable +repository.id.invalid=The given repository id {0} is not valid. +repository.not_found=The repository with the given id "{0}" was not found +repository.file.not_found=No file "{1}" found in the repository "{0}" +repository.scan.task_retrieval_failed=Could not get scan task information: {0}
\ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/pom.xml b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/pom.xml index 80e462062..2f5f27703 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/pom.xml +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/pom.xml @@ -117,6 +117,18 @@ <groupId>org.apache.archiva.components</groupId> <artifactId>archiva-components-spring-taskqueue</artifactId> </dependency> + <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-scheduler-indexing</artifactId> + </dependency> + <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-scheduler-repository</artifactId> + </dependency> + <dependency> + <groupId>org.apache.archiva.maven</groupId> + <artifactId>archiva-maven-scheduler</artifactId> + </dependency> <dependency> @@ -167,6 +179,11 @@ <!-- Test scope --> <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.apache.archiva</groupId> <artifactId>archiva-proxy</artifactId> <scope>test</scope> diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/admin/DefaultRepositoryTaskAdministration.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/admin/DefaultRepositoryTaskAdministration.java new file mode 100644 index 000000000..5dc9bb1dd --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/admin/DefaultRepositoryTaskAdministration.java @@ -0,0 +1,360 @@ +package org.apache.archiva.admin.repository.admin; +/* + * 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 org.apache.archiva.admin.model.RepositoryAdminException; +import org.apache.archiva.admin.model.admin.RepositoryTaskAdministration; +import org.apache.archiva.admin.model.beans.IndexingTask; +import org.apache.archiva.admin.model.beans.MetadataScanTask; +import org.apache.archiva.admin.model.beans.RepositoryTaskInfo; +import org.apache.archiva.admin.model.beans.ScanStatus; +import org.apache.archiva.components.taskqueue.TaskQueueException; +import org.apache.archiva.components.taskqueue.execution.TaskQueueExecutor; +import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager; +import org.apache.archiva.repository.RepositoryRegistry; +import org.apache.archiva.repository.storage.StorageAsset; +import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask; +import org.apache.archiva.scheduler.indexing.IndexingArchivaTaskScheduler; +import org.apache.archiva.scheduler.repository.model.RepositoryArchivaTaskScheduler; +import org.apache.archiva.scheduler.repository.model.RepositoryTask; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.inject.Named; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Martin Stockhammer <martin_s@apache.org> + */ +@Service( "repositoryTaskAdministration#default" ) +public class DefaultRepositoryTaskAdministration implements RepositoryTaskAdministration +{ + private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryTaskAdministration.class ); + + + final RepositoryRegistry repositoryRegistry; + + final + TaskQueueExecutor<ArtifactIndexingTask> indexingTaskExecutor; + + final + TaskQueueExecutor<RepositoryTask> scanningTaskExecutor; + + private final RepositoryArchivaTaskScheduler repositoryArchivaTaskScheduler; + + private final IndexingArchivaTaskScheduler indexingArchivaTaskScheduler; + + public DefaultRepositoryTaskAdministration( RepositoryRegistry repositoryRegistry, + @Named( value = "taskQueueExecutor#indexing" ) TaskQueueExecutor<ArtifactIndexingTask> indexingTaskExecutor, + @Named( value = "taskQueueExecutor#repository-scanning" ) TaskQueueExecutor<RepositoryTask> scanningTaskExecutor, + @Named( value = "archivaTaskScheduler#repository" ) RepositoryArchivaTaskScheduler repositoryArchivaTaskScheduler, + @Named( value = "archivaTaskScheduler#indexing" ) IndexingArchivaTaskScheduler indexingArchivaTaskScheduler) + { + this.repositoryRegistry = repositoryRegistry; + this.indexingTaskExecutor = indexingTaskExecutor; + this.scanningTaskExecutor = scanningTaskExecutor; + this.repositoryArchivaTaskScheduler = repositoryArchivaTaskScheduler; + this.indexingArchivaTaskScheduler = indexingArchivaTaskScheduler; + } + + @Override + public void scheduleFullScan( String repositoryId ) throws RepositoryAdminException + { + if ( StringUtils.isEmpty( repositoryId ) ) { + throw RepositoryAdminException.ofKey( "repository.id.invalid", "" ); + } + try + { + org.apache.archiva.repository.ManagedRepository repository = repositoryRegistry.getManagedRepository( repositoryId ); + if (repository==null) { + throw RepositoryAdminException.ofKey( "repository.not_found", repositoryId ); + } + ArtifactIndexingTask task = + new ArtifactIndexingTask( repository, null, ArtifactIndexingTask.Action.FINISH, repository.getIndexingContext( ) ); + task.setExecuteOnEntireRepo( true ); + task.setOnlyUpdate( false ); + indexingArchivaTaskScheduler.queueTask( task ); + repositoryArchivaTaskScheduler.queueTask( new RepositoryTask( repositoryId, true ) ); + } + catch ( TaskQueueException e ) + { + log.error( "Could not queue the task: {}", e.getMessage( ), e ); + throw RepositoryAdminException.ofKey( "repository.scan.task_queue_error", e, e.getMessage( ) ); + } + } + + @Override + public void scheduleIndexFullScan( String repositoryId ) throws RepositoryAdminException + { + if ( StringUtils.isEmpty( repositoryId ) ) { + throw RepositoryAdminException.ofKey( "repository.id.invalid", "" ); + } + try + { + org.apache.archiva.repository.ManagedRepository repository = repositoryRegistry.getManagedRepository( repositoryId ); + if (repository==null) { + throw RepositoryAdminException.ofKey( "repository.not_found", repositoryId ); + } + ArtifactIndexingTask task = + new ArtifactIndexingTask( repository, null, ArtifactIndexingTask.Action.FINISH, repository.getIndexingContext( ) ); + task.setExecuteOnEntireRepo( true ); + task.setOnlyUpdate( false ); + indexingArchivaTaskScheduler.queueTask( task ); + } + catch ( TaskQueueException e ) + { + log.error( "Could not queue the task: {}", e.getMessage( ), e ); + throw RepositoryAdminException.ofKey( "repository.scan.task_queue_error", e, e.getMessage( ) ); + } + } + + @Override + public void scheduleIndexScan( String repositoryId, String relativePath ) throws RepositoryAdminException + { + if ( StringUtils.isEmpty( repositoryId ) ) { + throw RepositoryAdminException.ofKey( "repository.id.invalid", "" ); + } + try + { + org.apache.archiva.repository.ManagedRepository repository = repositoryRegistry.getManagedRepository( repositoryId ); + if (repository==null) { + throw RepositoryAdminException.ofKey( "repository.not_found", repositoryId ); + } + StorageAsset asset = repository.getAsset( relativePath ); + if (!asset.exists()) { + throw RepositoryAdminException.ofKey( "repository.file.not_found", repositoryId, relativePath ); + } + ArtifactIndexingTask task = + new ArtifactIndexingTask( repository, asset.getFilePath( ), ArtifactIndexingTask.Action.FINISH, repository.getIndexingContext( ) ); + task.setExecuteOnEntireRepo( false ); + task.setOnlyUpdate( true ); + indexingArchivaTaskScheduler.queueTask( task ); + } + catch ( TaskQueueException e ) + { + log.error( "Could not queue the task: {}", e.getMessage( ), e ); + throw RepositoryAdminException.ofKey( "repository.scan.task_queue_error", e, e.getMessage( ) ); + } + + } + + @Override + public void scheduleMetadataFullScan( String repositoryId ) throws RepositoryAdminException + { + if ( StringUtils.isEmpty( repositoryId ) ) { + throw RepositoryAdminException.ofKey( "repository.id.invalid", "" ); + } + try + { + org.apache.archiva.repository.ManagedRepository repository = repositoryRegistry.getManagedRepository( repositoryId ); + if (repository==null) { + throw RepositoryAdminException.ofKey( "repository.not_found", repositoryId ); + } + repositoryArchivaTaskScheduler.queueTask( new RepositoryTask( repositoryId, true ) ); + } + catch ( TaskQueueException e ) + { + log.error( "Could not queue the task: {}", e.getMessage( ), e ); + throw RepositoryAdminException.ofKey( "repository.scan.task_queue_error", e, e.getMessage( ) ); + } + + } + + @Override + public void scheduleMetadataUpdateScan( String repositoryId ) throws RepositoryAdminException + { + if ( StringUtils.isEmpty( repositoryId ) ) { + throw RepositoryAdminException.ofKey( "repository.id.invalid", "" ); + } + try + { + org.apache.archiva.repository.ManagedRepository repository = repositoryRegistry.getManagedRepository( repositoryId ); + if (repository==null) { + throw RepositoryAdminException.ofKey( "repository.not_found", repositoryId ); + } + repositoryArchivaTaskScheduler.queueTask( new RepositoryTask( repositoryId, false ) ); + } + catch ( TaskQueueException e ) + { + log.error( "Could not queue the task: {}", e.getMessage( ), e ); + throw RepositoryAdminException.ofKey( "repository.scan.task_queue_error", e, e.getMessage( ) ); + } + + } + + public static MetadataScanTask getMetadataScanTaskInfo(RepositoryTask repositoryTask) { + MetadataScanTask scanTask = new MetadataScanTask( ); + scanTask.setFullScan( repositoryTask.isScanAll()); + scanTask.setUpdateRelatedArtifacts( repositoryTask.isUpdateRelatedArtifacts() ); + StorageAsset file = repositoryTask.getResourceFile( ); + scanTask.setResource( repositoryTask.getResourceFile( )==null?"":repositoryTask.getResourceFile().toString( ) ); + scanTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTime() ); + scanTask.setRepositoryId( repositoryTask.getRepositoryId( ) ); + return scanTask; + } + + public static IndexingTask getIndexingTaskInfo(ArtifactIndexingTask repositoryTask) { + IndexingTask indexingTask = new IndexingTask( ); + indexingTask.setFullScan( repositoryTask.isExecuteOnEntireRepo()); + indexingTask.setUpdateOnly( repositoryTask.isOnlyUpdate() ); + indexingTask.setResource( repositoryTask.getResourceFile( )==null?"":repositoryTask.getResourceFile().toString( ) ); + indexingTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTime() ); + indexingTask.setRepositoryId( repositoryTask.getRepository().getId() ); + return indexingTask; + + } + + public void updateScanInfo( ScanStatus scanStatus, RepositoryTask runningRepositoryTask, List<RepositoryTask> taskQueue) { + List<MetadataScanTask> newScanQueue = new ArrayList<>( ); + if (runningRepositoryTask!=null) { + MetadataScanTask taskInfo = getMetadataScanTaskInfo( runningRepositoryTask ); + taskInfo.setRunning( true ); + newScanQueue.add( 0, taskInfo); + } + newScanQueue.addAll( taskQueue.stream( ).map( task -> getMetadataScanTaskInfo( task ) ).collect( Collectors.toList( ) ) ); + scanStatus.setScanQueue( newScanQueue ); + } + + public void updateIndexInfo( ScanStatus scanStatus, ArtifactIndexingTask runningIndexingTask, List<ArtifactIndexingTask> taskQueue) { + List<IndexingTask> newIndexQueue = new ArrayList<>( ); + if (runningIndexingTask!=null) { + IndexingTask taskInfo = getIndexingTaskInfo( runningIndexingTask ); + taskInfo.setRunning( true ); + newIndexQueue.add(taskInfo ); + } + newIndexQueue.addAll( taskQueue.stream( ).map( task -> getIndexingTaskInfo( task ) ).collect( Collectors.toList( ) ) ); + scanStatus.setIndexingQueue( newIndexQueue ); + } + + + @Override + public ScanStatus getCurrentScanStatus( String repositoryId ) throws RepositoryAdminException + { + if ( StringUtils.isEmpty( repositoryId ) ) { + throw RepositoryAdminException.ofKey( "repository.id.invalid", "" ); + } + org.apache.archiva.repository.ManagedRepository repository = repositoryRegistry.getManagedRepository( repositoryId ); + if (repository==null) { + throw RepositoryAdminException.ofKey( "repository.not_found", repositoryId ); + } + ScanStatus status = new ScanStatus( ); + try + { + RepositoryTask scanTask = scanningTaskExecutor.getCurrentTask( ); + if ( scanTask!=null && !repositoryId.equals( scanTask.getRepositoryId( ) ) ) + { + scanTask = null; + } + ArtifactIndexingTask indexTask = indexingTaskExecutor.getCurrentTask( ); + if ( indexTask!=null && !repositoryId.equals( indexTask.getRepository( ).getId( ) ) ) + { + indexTask = null; + } + updateScanInfo( status, scanTask, scanningTaskExecutor.getQueue( ).getQueueSnapshot( ).stream( ).filter( task -> repositoryId.equals( task.getRepositoryId( ) ) ).collect( Collectors.toList( ) ) ); + updateIndexInfo( status, indexTask, indexingTaskExecutor.getQueue( ).getQueueSnapshot( ).stream( ).filter( task -> repositoryId.equals( task.getRepository( ).getId( ) ) ).collect( Collectors.toList( ) ) ); + return status; + } + catch ( TaskQueueException e ) + { + log.error( "Could not get task information: {}", e.getMessage( ), e ); + throw RepositoryAdminException.ofKey( "repository.scan.task_retrieval_failed", e.getMessage( ) ); + } + + } + + @Override + public ScanStatus getCurrentScanStatus( ) throws RepositoryAdminException + { + ScanStatus status = new ScanStatus( ); + try + { + RepositoryTask scanTask = scanningTaskExecutor.getCurrentTask( ); + ArtifactIndexingTask indexTask = indexingTaskExecutor.getCurrentTask( ); + updateScanInfo( status, scanTask, scanningTaskExecutor.getQueue( ).getQueueSnapshot() ); + updateIndexInfo( status, indexTask, indexingTaskExecutor.getQueue( ).getQueueSnapshot( ) ); + return status; + } + catch ( TaskQueueException e ) + { + log.error( "Could not get task information: {}", e.getMessage( ), e ); + throw RepositoryAdminException.ofKey( "repository.scan.task_retrieval_failed", e.getMessage( ) ); + } + + } + + @Override + public List<RepositoryTaskInfo> cancelTasks( String repositoryId ) throws RepositoryAdminException + { + ArrayList<RepositoryTaskInfo> resultList = new ArrayList<>( ); + resultList.addAll( cancelScanTasks( repositoryId ) ); + resultList.addAll( cancelIndexTasks( repositoryId ) ); + return resultList; + } + + @Override + public List<RepositoryTaskInfo> cancelScanTasks( String repositoryId ) throws RepositoryAdminException + { + try + { + ArrayList<RepositoryTaskInfo> resultList = new ArrayList<>( ); + List<RepositoryTask> removeTasks = scanningTaskExecutor.getQueue( ).getQueueSnapshot( ).stream( ).filter( task -> repositoryId.equals( task.getRepositoryId() ) ).collect( Collectors.toList( ) ); + scanningTaskExecutor.getQueue( ).removeAll( removeTasks ); + RepositoryTask currentTask = scanningTaskExecutor.getCurrentTask( ); + if ( currentTask != null && repositoryId.equals( currentTask.getRepositoryId()) ) + { + scanningTaskExecutor.cancelTask( currentTask ); + resultList.add( getMetadataScanTaskInfo( currentTask ) ); + } + resultList.addAll( removeTasks.stream( ).map( task -> getMetadataScanTaskInfo( task ) ).collect( Collectors.toList( ) ) ); + return resultList; + } + catch ( TaskQueueException e ) + { + throw RepositoryAdminException.ofKey( "repository.task.dequeue_failed", repositoryId ); + } + } + + @Override + public List<RepositoryTaskInfo> cancelIndexTasks( String repositoryId ) throws RepositoryAdminException + { + try + { + ArrayList<RepositoryTaskInfo> resultList = new ArrayList<>( ); + List<ArtifactIndexingTask> removeTasks = indexingTaskExecutor.getQueue( ).getQueueSnapshot( ).stream( ).filter( task -> repositoryId.equals( task.getRepository( ).getId( ) ) ).collect( Collectors.toList( ) ); + indexingTaskExecutor.getQueue( ).removeAll( removeTasks ); + ArtifactIndexingTask currentTask = indexingTaskExecutor.getCurrentTask( ); + if ( currentTask != null && repositoryId.equals( currentTask.getRepository( ).getId( ) ) ) + { + indexingTaskExecutor.cancelTask( currentTask ); + resultList.add( getIndexingTaskInfo( currentTask ) ); + } + resultList.addAll( removeTasks.stream( ).map( task -> getIndexingTaskInfo( task ) ).collect( Collectors.toList( ) ) ); + return resultList; + } + catch ( TaskQueueException e ) + { + throw RepositoryAdminException.ofKey( "repository.task.dequeue_failed", repositoryId ); + } + } + + +} diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MockRepositoryArchivaTaskScheduler.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MockRepositoryArchivaTaskScheduler.java index 8c3cfe264..1540b4670 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MockRepositoryArchivaTaskScheduler.java +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MockRepositoryArchivaTaskScheduler.java @@ -26,7 +26,7 @@ import org.springframework.stereotype.Service; /** * @author Olivier Lamy */ -@Service("archivaTaskScheduler#repository") +@Service("archivaTaskScheduler#mock") public class MockRepositoryArchivaTaskScheduler implements RepositoryArchivaTaskScheduler { diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/admin/RepositoryTaskAdministrationTest.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/admin/RepositoryTaskAdministrationTest.java new file mode 100644 index 000000000..6cdf31a6b --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/admin/RepositoryTaskAdministrationTest.java @@ -0,0 +1,267 @@ +package org.apache.archiva.admin.repository.admin; +/* + * 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 org.apache.archiva.admin.model.RepositoryAdminException; +import org.apache.archiva.admin.model.admin.RepositoryTaskAdministration; +import org.apache.archiva.admin.model.beans.ScanStatus; +import org.apache.archiva.components.taskqueue.TaskQueue; +import org.apache.archiva.components.taskqueue.TaskQueueException; +import org.apache.archiva.components.taskqueue.execution.TaskQueueExecutor; +import org.apache.archiva.repository.ManagedRepository; +import org.apache.archiva.repository.RepositoryRegistry; +import org.apache.archiva.repository.storage.StorageAsset; +import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask; +import org.apache.archiva.scheduler.indexing.IndexingArchivaTaskScheduler; +import org.apache.archiva.scheduler.repository.model.RepositoryArchivaTaskScheduler; +import org.apache.archiva.scheduler.repository.model.RepositoryTask; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * @author Martin Stockhammer <martin_s@apache.org> + */ +@Tag( "archiva-admin" ) +@DisplayName( "Unit Tests for RepositoryTaskAdministration" ) +public class RepositoryTaskAdministrationTest +{ + + private RepositoryTaskAdministration taskAdministration; + private TaskQueueExecutor<ArtifactIndexingTask> indexingTaskExecutor; + private TaskQueueExecutor<RepositoryTask> scanningTaskExecutor; + private RepositoryArchivaTaskScheduler repositoryArchivaTaskScheduler; + private IndexingArchivaTaskScheduler indexingArchivaTaskScheduler; + private RepositoryRegistry registry; + + @BeforeEach + public void init() { + registry = mock( RepositoryRegistry.class ); + indexingTaskExecutor = mock( TaskQueueExecutor.class ); + scanningTaskExecutor = mock( TaskQueueExecutor.class ); + repositoryArchivaTaskScheduler = mock( RepositoryArchivaTaskScheduler.class ); + indexingArchivaTaskScheduler = mock( IndexingArchivaTaskScheduler.class ); + this.taskAdministration = new DefaultRepositoryTaskAdministration( registry, indexingTaskExecutor, + scanningTaskExecutor, repositoryArchivaTaskScheduler, indexingArchivaTaskScheduler ); + } + + @Test + public void testScanStatus() throws RepositoryAdminException, TaskQueueException + { + TaskQueue queue = mock( TaskQueue.class ); + TaskQueue indexQueue = mock( TaskQueue.class ); + + List<RepositoryTask> scanList = new ArrayList<>( ); + RepositoryTask scanTask1 = new RepositoryTask( ); + scanTask1.setRepositoryId( "abcde" ); + scanTask1.setScanAll( true ); + scanTask1.setResourceFile( null ); + scanList.add( scanTask1 ); + RepositoryTask scanTask2 = new RepositoryTask( ); + scanTask2.setRepositoryId( "testrepo2" ); + scanTask2.setScanAll( true ); + scanTask2.setResourceFile( null ); + scanList.add( scanTask1 ); + + List<ArtifactIndexingTask> indexList = new ArrayList<>( ); + ArtifactIndexingTask indexTask1 = mock( ArtifactIndexingTask.class, RETURNS_DEEP_STUBS ); + when( indexTask1.getRepository( ).getId( ) ).thenReturn( "indexrepo1" ); + when( indexTask1.isExecuteOnEntireRepo( ) ).thenReturn( true ); + when( indexTask1.getResourceFile( ) ).thenReturn( null ); + indexList.add( indexTask1 ); + ArtifactIndexingTask indexTask2 = mock( ArtifactIndexingTask.class, RETURNS_DEEP_STUBS ); + when( indexTask2.getRepository( ).getId( ) ).thenReturn( "indexrepo2" ); + when( indexTask2.isExecuteOnEntireRepo( ) ).thenReturn( true ); + when( indexTask2.getResourceFile( ) ).thenReturn( null ); + indexList.add( indexTask2 ); + + when( scanningTaskExecutor.getQueue( ) ).thenReturn( queue ); + when( indexingTaskExecutor.getQueue( ) ).thenReturn( indexQueue ); + when( queue.getQueueSnapshot( ) ).thenReturn( scanList ); + when( indexQueue.getQueueSnapshot( ) ).thenReturn( indexList ); + ScanStatus currentScanStatus = taskAdministration.getCurrentScanStatus( ); + assertNotNull( currentScanStatus ); + assertNotNull( currentScanStatus.getIndexingQueue( ) ); + assertNotNull( currentScanStatus.getScanQueue( ) ); + assertEquals( 2, currentScanStatus.getScanQueue( ).size( ) ); + assertEquals( 2, currentScanStatus.getIndexingQueue( ).size( ) ); + } + + @Test + public void testScanStatusWithId() throws RepositoryAdminException, TaskQueueException + { + TaskQueue queue = mock( TaskQueue.class ); + TaskQueue indexQueue = mock( TaskQueue.class ); + + List<RepositoryTask> scanList = new ArrayList<>( ); + RepositoryTask scanTask1 = new RepositoryTask( ); + scanTask1.setRepositoryId( "abcde" ); + scanTask1.setScanAll( true ); + scanTask1.setResourceFile( null ); + scanList.add( scanTask1 ); + RepositoryTask scanTask2 = new RepositoryTask( ); + scanTask2.setRepositoryId( "testrepo2" ); + scanTask2.setScanAll( true ); + scanTask2.setResourceFile( null ); + scanList.add( scanTask1 ); + + List<ArtifactIndexingTask> indexList = new ArrayList<>( ); + ArtifactIndexingTask indexTask1 = mock( ArtifactIndexingTask.class, RETURNS_DEEP_STUBS ); + when( indexTask1.getRepository( ).getId( ) ).thenReturn( "indexrepo1" ); + when( indexTask1.isExecuteOnEntireRepo( ) ).thenReturn( true ); + when( indexTask1.getResourceFile( ) ).thenReturn( null ); + indexList.add( indexTask1 ); + ArtifactIndexingTask indexTask2 = mock( ArtifactIndexingTask.class, RETURNS_DEEP_STUBS ); + when( indexTask2.getRepository( ).getId( ) ).thenReturn( "indexrepo2" ); + when( indexTask2.isExecuteOnEntireRepo( ) ).thenReturn( true ); + when( indexTask2.getResourceFile( ) ).thenReturn( null ); + indexList.add( indexTask2 ); + + when( scanningTaskExecutor.getQueue( ) ).thenReturn( queue ); + when( indexingTaskExecutor.getQueue( ) ).thenReturn( indexQueue ); + when( queue.getQueueSnapshot( ) ).thenReturn( scanList ); + when( indexQueue.getQueueSnapshot( ) ).thenReturn( indexList ); + when( registry.getManagedRepository( "indexrepo2" ) ).thenReturn( mock( ManagedRepository.class ) ); + ScanStatus currentScanStatus = taskAdministration.getCurrentScanStatus( "indexrepo2"); + assertNotNull( currentScanStatus ); + assertNotNull( currentScanStatus.getIndexingQueue( ) ); + assertNotNull( currentScanStatus.getScanQueue( ) ); + assertEquals( 0, currentScanStatus.getScanQueue( ).size( ) ); + assertEquals( 1, currentScanStatus.getIndexingQueue( ).size( ) ); + } + + @Test + public void testScheduleFullScan() throws RepositoryAdminException, TaskQueueException + { + when( registry.getManagedRepository( "internal" ) ).thenReturn( mock( ManagedRepository.class ) ); + taskAdministration.scheduleFullScan( "internal" ); + verify( repositoryArchivaTaskScheduler, times(1) ).queueTask( any() ); + verify( indexingArchivaTaskScheduler, times(1) ).queueTask( any() ); + } + + @Test + public void testScheduleIndexScan() throws RepositoryAdminException, TaskQueueException + { + when( registry.getManagedRepository( "internal" ) ).thenReturn( mock( ManagedRepository.class ) ); + taskAdministration.scheduleIndexFullScan( "internal" ); + ArgumentCaptor<ArtifactIndexingTask> captor = ArgumentCaptor.forClass( ArtifactIndexingTask.class ); + verify( repositoryArchivaTaskScheduler, times(0) ).queueTask( any() ); + verify( indexingArchivaTaskScheduler, times(1) ).queueTask( captor.capture() ); + assertTrue(captor.getValue().isExecuteOnEntireRepo()); + } + + @Test + public void testScheduleIndexScanWithFile() throws RepositoryAdminException, TaskQueueException + { + ManagedRepository managedRepo = mock( ManagedRepository.class, RETURNS_DEEP_STUBS ); + when( registry.getManagedRepository( "internal" ) ).thenReturn( managedRepo ); + StorageAsset asset = mock( StorageAsset.class ); + when( asset.getFilePath( ) ).thenReturn( Paths.get( "abc/def/ghij.pom" ) ); + when( asset.exists( ) ).thenReturn( true ); + when( registry.getManagedRepository( "internal" ).getAsset( "abc/def/ghij.pom" ) ).thenReturn( asset ); + taskAdministration.scheduleIndexScan( "internal", "abc/def/ghij.pom" ); + ArgumentCaptor<ArtifactIndexingTask> captor = ArgumentCaptor.forClass( ArtifactIndexingTask.class ); + verify( repositoryArchivaTaskScheduler, times(0) ).queueTask( any() ); + verify( indexingArchivaTaskScheduler, times(1) ).queueTask( captor.capture() ); + ArtifactIndexingTask caption = captor.getValue( ); + assertFalse(caption.isExecuteOnEntireRepo()); + assertEquals( "abc/def/ghij.pom", caption.getResourceFile( ).toString() ); + } + + @Test + public void testScheduleMetadataScan() throws RepositoryAdminException, TaskQueueException + { + when( registry.getManagedRepository( "internal" ) ).thenReturn( mock( ManagedRepository.class ) ); + taskAdministration.scheduleMetadataFullScan( "internal" ); + ArgumentCaptor<RepositoryTask> captor = ArgumentCaptor.forClass( RepositoryTask.class ); + verify( repositoryArchivaTaskScheduler, times(1) ).queueTask( captor.capture( ) ); + verify( indexingArchivaTaskScheduler, times(0) ).queueTask( any() ); + assertTrue(captor.getValue().isScanAll()); + } + + @Test + public void testScheduleMetadataUpdateScan() throws RepositoryAdminException, TaskQueueException + { + when( registry.getManagedRepository( "internal" ) ).thenReturn( mock( ManagedRepository.class ) ); + taskAdministration.scheduleMetadataUpdateScan( "internal" ); + ArgumentCaptor<RepositoryTask> captor = ArgumentCaptor.forClass( RepositoryTask.class ); + verify( repositoryArchivaTaskScheduler, times(1) ).queueTask( captor.capture( ) ); + verify( indexingArchivaTaskScheduler, times(0) ).queueTask( any() ); + assertFalse(captor.getValue().isScanAll()); + } + + + @Test + void cancelAllTasks() throws TaskQueueException, RepositoryAdminException + { + TaskQueue queue = mock( TaskQueue.class ); + TaskQueue indexQueue = mock( TaskQueue.class ); + + List<RepositoryTask> scanList = new ArrayList<>( ); + RepositoryTask scanTask1 = new RepositoryTask( ); + scanTask1.setRepositoryId( "abcde" ); + scanTask1.setScanAll( true ); + scanTask1.setResourceFile( null ); + scanList.add( scanTask1 ); + RepositoryTask scanTask2 = new RepositoryTask( ); + scanTask2.setRepositoryId( "testrepo2" ); + scanTask2.setScanAll( true ); + scanTask2.setResourceFile( null ); + scanList.add( scanTask1 ); + + List<ArtifactIndexingTask> indexList = new ArrayList<>( ); + ArtifactIndexingTask indexTask1 = mock( ArtifactIndexingTask.class, RETURNS_DEEP_STUBS ); + when( indexTask1.getRepository( ).getId( ) ).thenReturn( "indexrepo1" ); + when( indexTask1.isExecuteOnEntireRepo( ) ).thenReturn( true ); + when( indexTask1.getResourceFile( ) ).thenReturn( null ); + indexList.add( indexTask1 ); + ArtifactIndexingTask indexTask2 = mock( ArtifactIndexingTask.class, RETURNS_DEEP_STUBS ); + when( indexTask2.getRepository( ).getId( ) ).thenReturn( "indexrepo2" ); + when( indexTask2.isExecuteOnEntireRepo( ) ).thenReturn( true ); + when( indexTask2.getResourceFile( ) ).thenReturn( null ); + indexList.add( indexTask2 ); + + when( scanningTaskExecutor.getQueue( ) ).thenReturn( queue ); + when( indexingTaskExecutor.getQueue( ) ).thenReturn( indexQueue ); + when( queue.getQueueSnapshot( ) ).thenReturn( scanList ); + when( indexQueue.getQueueSnapshot( ) ).thenReturn( indexList ); + taskAdministration.cancelTasks( "indexrepo1" ); + ArgumentCaptor<List> scanCaptor = ArgumentCaptor.forClass( List.class ); + ArgumentCaptor<List> indexCaptor = ArgumentCaptor.forClass( List.class ); + + verify( queue ).removeAll( scanCaptor.capture() ); + verify( indexQueue ).removeAll( indexCaptor.capture() ); + + List scanCancelList = scanCaptor.getValue( ); + List indexCancelList = indexCaptor.getValue( ); + assertEquals( 0, scanCancelList.size( ) ); + assertEquals( 1, indexCancelList.size( ) ); + assertEquals( "indexrepo1", ( (ArtifactIndexingTask) indexCancelList.get( 0 ) ).getRepository( ).getId( ) ); + + + } +} diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/spring-context.xml b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/spring-context.xml index 5c201e56f..203c32674 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/spring-context.xml +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/spring-context.xml @@ -31,8 +31,9 @@ default-lazy-init="true"> <context:annotation-config/> - <context:component-scan base-package="org.apache.archiva.admin.mock,org.apache.archiva.repository.content.maven2"/> + <context:component-scan base-package="org.apache.archiva.admin.mock,org.apache.archiva.repository.content.base"/> + <alias name="archivaTaskScheduler#mock" alias="archivaTaskScheduler#default" /> <bean name="scheduler" class="org.apache.archiva.components.scheduler.DefaultScheduler"> <property name="properties"> <props> |