aboutsummaryrefslogtreecommitdiffstats
path: root/archiva-modules/archiva-base
diff options
context:
space:
mode:
authorMartin Stockhammer <martin_s@apache.org>2021-01-27 20:16:26 +0100
committerMartin Stockhammer <martin_s@apache.org>2021-01-27 20:16:26 +0100
commitb32d75a85b4f5805d6d251ea2237f838087aa2bf (patch)
tree162037148959d4bddb68ef7a7aa22ea89a69759f /archiva-modules/archiva-base
parent7eef53d7c5145de75ecb6734169bacb53b02f5a0 (diff)
downloadarchiva-b32d75a85b4f5805d6d251ea2237f838087aa2bf.tar.gz
archiva-b32d75a85b4f5805d6d251ea2237f838087aa2bf.zip
Adding task admin implementation
Diffstat (limited to 'archiva-modules/archiva-base')
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/AbstractArtifactConsumerTest.java15
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java10
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/spring-context-cleanup-released-snapshots.xml2
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/admin/ArchivaAdministration.java1
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/admin/RepositoryTaskAdministration.java115
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/IndexingTask.java87
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/MetadataScanTask.java84
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RepositoryTaskInfo.java121
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/ScanStatus.java85
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/resources/org/apache/archiva/admin/model/error/AdminErrors.properties4
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/pom.xml17
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/admin/DefaultRepositoryTaskAdministration.java360
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/mock/MockRepositoryArchivaTaskScheduler.java2
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/admin/RepositoryTaskAdministrationTest.java267
-rw-r--r--archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/spring-context.xml3
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>