This is an automated email from the ASF dual-hosted git repository.

martin_s pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/archiva.git


The following commit(s) were added to refs/heads/master by this push:
     new b32d75a  Adding task admin implementation
b32d75a is described below

commit b32d75a85b4f5805d6d251ea2237f838087aa2bf
Author: Martin Stockhammer <[email protected]>
AuthorDate: Wed Jan 27 20:16:26 2021 +0100

    Adding task admin implementation
---
 .../core/AbstractArtifactConsumerTest.java         |  15 +-
 .../repository/AbstractRepositoryPurgeTest.java    |  10 +-
 .../spring-context-cleanup-released-snapshots.xml  |   2 +-
 .../admin/model/admin/ArchivaAdministration.java   |   1 +
 .../model/admin/RepositoryTaskAdministration.java  | 115 +++++++
 .../archiva/admin/model/beans/IndexingTask.java    |  87 +++++
 .../admin/model/beans/MetadataScanTask.java        |  84 +++++
 .../admin/model/beans/RepositoryTaskInfo.java      | 121 +++++++
 .../archiva/admin/model/beans/ScanStatus.java      |  85 +++++
 .../admin/model/error/AdminErrors.properties       |   4 +
 .../archiva-repository-admin-default/pom.xml       |  17 +
 .../admin/DefaultRepositoryTaskAdministration.java | 360 +++++++++++++++++++++
 .../mock/MockRepositoryArchivaTaskScheduler.java   |   2 +-
 .../admin/RepositoryTaskAdministrationTest.java    | 267 +++++++++++++++
 .../src/test/resources/spring-context.xml          |   3 +-
 .../archiva/rest/api/model/v2/IndexingTask.java    |  12 +-
 .../archiva/rest/api/model/v2/Repository.java      |  12 +-
 .../archiva/rest/api/model/v2/ScanStatus.java      |  35 +-
 .../apache/archiva/rest/api/model/v2/ScanTask.java |   9 +-
 .../archiva/rest/api}/services/v2/ErrorKeys.java   |   2 +-
 .../rest/api/services/v2/RepositoryService.java    |   4 -
 .../v2/DefaultMavenManagedRepositoryService.java   |   1 +
 .../services/v2/DefaultRepositoryGroupService.java |   1 +
 .../rest/services/v2/DefaultRepositoryService.java | 112 +++----
 .../v2/DefaultSecurityConfigurationService.java    |   5 +-
 .../services/v2/NativeRepositoryServiceTest.java   | 162 ++++++++++
 26 files changed, 1420 insertions(+), 108 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 d6b116e..0ff779f 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 cfcd19e..2f906a5 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 2f64658..ee3d8e0 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 7037f49..beda0b9 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 0000000..0375f2e
--- /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 <[email protected]>
+ * @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 0000000..8b39c20
--- /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 <[email protected]>
+ */
+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 0000000..02ab7ee
--- /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 <[email protected]>
+ */
+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 0000000..9a0a838
--- /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 <[email protected]>
+ */
+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 0000000..50dc46e
--- /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 <[email protected]>
+ */
+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 4addc0a..82056a0 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 80e4620..2f5f277 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 0000000..5dc9bb1
--- /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 <[email protected]>
+ */
+@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 8c3cfe2..1540b46 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 0000000..6cdf31a
--- /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 <[email protected]>
+ */
+@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 5c201e5..203c326 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>
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/IndexingTask.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/IndexingTask.java
index e4d6684..b3bc509 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/IndexingTask.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/IndexingTask.java
@@ -37,13 +37,13 @@ public class IndexingTask implements Serializable
     private boolean running = false;
     private long maxExecutionTimeMs = 0;
 
-    public static IndexingTask of( ArtifactIndexingTask repositoryTask ) {
+    public static IndexingTask of( 
org.apache.archiva.admin.model.beans.IndexingTask repositoryTask ) {
         IndexingTask indexingTask = new IndexingTask( );
-        indexingTask.setFullRepository( 
repositoryTask.isExecuteOnEntireRepo());
-        indexingTask.setUpdateOnly( repositoryTask.isOnlyUpdate() );
-        indexingTask.setResource( repositoryTask.getResourceFile( ).toString( 
) );
-        indexingTask.setMaxExecutionTimeMs( 
repositoryTask.getMaxExecutionTime() );
-        indexingTask.setRepositoryId( repositoryTask.getRepository().getId() );
+        indexingTask.setFullRepository( repositoryTask.isFullScan());
+        indexingTask.setUpdateOnly( repositoryTask.isUpdateOnly() );
+        indexingTask.setResource( repositoryTask.getResource() );
+        indexingTask.setMaxExecutionTimeMs( 
repositoryTask.getMaxExecutionTimeMs() );
+        indexingTask.setRepositoryId( repositoryTask.getRepositoryId() );
         return indexingTask;
     }
 
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Repository.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Repository.java
index ea4993d..04f77b9 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Repository.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Repository.java
@@ -97,10 +97,18 @@ public class Repository implements Serializable
         } else {
             myLocale = locale;
         }
+        String repoName = repository.getName( myLocale );
+        if (repoName==null) {
+            repoName = repository.getName( );
+        }
+        String description = repository.getDescription( myLocale );
+        if (description==null)  {
+            description = repository.getDescription( );
+        }
         Repository newRepo = new Repository( );
         newRepo.setId( repository.getId() );
-        newRepo.setName( repository.getName( myLocale ) );
-        newRepo.setDescription( repository.getDescription( myLocale ) );
+        newRepo.setName( repoName );
+        newRepo.setDescription( description );
         newRepo.setLocation( repository.getLocation().toASCIIString() );
         newRepo.setIndex( repository.hasIndex() );
         newRepo.setLayout( repository.getLayout() );
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanStatus.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanStatus.java
index 9800bbb..27c6b02 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanStatus.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanStatus.java
@@ -18,6 +18,7 @@ package org.apache.archiva.rest.api.model.v2;
  */
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.admin.model.beans.MetadataScanTask;
 import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
 import org.apache.archiva.scheduler.repository.model.RepositoryTask;
 
@@ -43,30 +44,18 @@ public class ScanStatus implements Serializable
     {
     }
 
-    public void updateScanInfo( RepositoryTask runningRepositoryTask, 
List<RepositoryTask> taskQueue) {
-        List<ScanTask> newScanQueue = new ArrayList<>( );
-        if (runningRepositoryTask==null) {
-            this.scanRunning=false;
-        } else {
-            this.scanRunning=true;
-            newScanQueue.add( 0, ScanTask.of( runningRepositoryTask ) );
-        }
-        newScanQueue.addAll( taskQueue.stream( ).map( task -> ScanTask.of( 
task ) ).collect( Collectors.toList( ) ) );
-        this.scanQueued = taskQueue.size( );
-        this.scanQueue = newScanQueue;
-    }
+    public static ScanStatus of( 
org.apache.archiva.admin.model.beans.ScanStatus modelStatus ) {
+        ScanStatus status = new ScanStatus( );
+        status.setIndexRunning( modelStatus.isIndexScanRunning() );
+        status.setScanRunning( modelStatus.isMetadataScanRunning() );
+        List<org.apache.archiva.admin.model.beans.IndexingTask> indexQueue = 
modelStatus.getIndexingQueue( );
+        status.setIndexingQueue( 
indexQueue.stream().map(IndexingTask::of).collect( Collectors.toList()) );
+        status.setIndexQueued( indexQueue.size( ) > 0 ? indexQueue.size( ) - 1 
: 0 );
+        List<MetadataScanTask> scanQueue = modelStatus.getScanQueue( );
+        status.setScanQueue( scanQueue.stream().map( ScanTask::of ).collect( 
Collectors.toList()) );
+        status.setScanQueued( scanQueue.size( ) > 0 ? scanQueue.size( ) - 1 : 
0 );
+        return status;
 
-    public void updateIndexInfo( ArtifactIndexingTask runningIndexingTask, 
List<ArtifactIndexingTask> taskQueue) {
-        List<IndexingTask> newIndexQueue = new ArrayList<>(  );
-        if (runningIndexingTask==null) {
-            this.indexRunning=false;
-        } else {
-            this.indexRunning=true;
-            newIndexQueue.add(IndexingTask.of( runningIndexingTask ) );
-        }
-        newIndexQueue.addAll( taskQueue.stream( ).map( task -> 
IndexingTask.of( task ) ).collect( Collectors.toList( ) ) );
-        this.indexQueued = taskQueue.size( );
-        this.indexingQueue = newIndexQueue;
     }
 
     @Schema( name = "scan_running", description = "True, if a scan is 
currently running" )
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanTask.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanTask.java
index 96aa96f..1dc1530 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanTask.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanTask.java
@@ -18,6 +18,7 @@ package org.apache.archiva.rest.api.model.v2;
  */
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.admin.model.beans.MetadataScanTask;
 import org.apache.archiva.scheduler.repository.model.RepositoryTask;
 
 import java.io.Serializable;
@@ -36,12 +37,12 @@ public class ScanTask implements Serializable
     private String resource = "";
     private long maxExecutionTimeMs = 0;
 
-    public static ScanTask of( RepositoryTask repositoryTask ) {
+    public static ScanTask of( MetadataScanTask repositoryTask ) {
         ScanTask scanTask = new ScanTask( );
-        scanTask.setFullRepository( repositoryTask.isScanAll());
+        scanTask.setFullRepository( repositoryTask.isFullScan());
         scanTask.setUpdateRelatedArtifacts( 
repositoryTask.isUpdateRelatedArtifacts() );
-        scanTask.setResource( repositoryTask.getResourceFile( ).toString( ) );
-        scanTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTime() );
+        scanTask.setResource( repositoryTask.getResource() );
+        scanTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTimeMs() 
);
         scanTask.setRepositoryId( repositoryTask.getRepositoryId( ) );
         return scanTask;
     }
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/ErrorKeys.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java
similarity index 98%
rename from 
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/ErrorKeys.java
rename to 
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java
index 5544ff3..c328a48 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/ErrorKeys.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java
@@ -1,4 +1,4 @@
-package org.apache.archiva.rest.services.v2;/*
+package org.apache.archiva.rest.api.services.v2;/*
  * 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
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java
index 8092ac7..4063977 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java
@@ -144,10 +144,6 @@ public interface RepositoryService
         throws ArchivaRestServiceException;
 
 
-    /**
-     * scan directories
-     * @since 1.4-M3
-     */
     @Path ("managed/{id}/scan/now")
     @POST
     @Produces ({ APPLICATION_JSON })
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java
index 3c9c3a6..e380a24 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java
@@ -24,6 +24,7 @@ import org.apache.archiva.components.rest.util.QueryHelper;
 import org.apache.archiva.rest.api.model.v2.FileInfo;
 import org.apache.archiva.rest.api.model.v2.MavenManagedRepository;
 import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
+import org.apache.archiva.rest.api.services.v2.ErrorKeys;
 import org.apache.archiva.rest.api.services.v2.ErrorMessage;
 import org.apache.archiva.rest.api.services.v2.MavenManagedRepositoryService;
 import org.slf4j.Logger;
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java
index 42b7193..9290873 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java
@@ -46,6 +46,7 @@ import 
org.apache.archiva.redback.rest.services.RedbackRequestInformation;
 import org.apache.archiva.redback.users.User;
 import org.apache.archiva.rest.api.model.v2.RepositoryGroup;
 import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
+import org.apache.archiva.rest.api.services.v2.ErrorKeys;
 import org.apache.archiva.rest.api.services.v2.ErrorMessage;
 import org.apache.archiva.rest.api.services.v2.RepositoryGroupService;
 import org.apache.commons.lang3.StringUtils;
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java
index 4f34cd1..7e41b09 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java
@@ -17,11 +17,10 @@ package org.apache.archiva.rest.services.v2;
  * under the License.
  */
 
+import org.apache.archiva.admin.model.RepositoryAdminException;
+import org.apache.archiva.admin.model.admin.RepositoryTaskAdministration;
 import org.apache.archiva.components.rest.model.PagedResult;
 import org.apache.archiva.components.rest.util.QueryHelper;
-import org.apache.archiva.components.taskqueue.Task;
-import org.apache.archiva.components.taskqueue.TaskQueueException;
-import org.apache.archiva.components.taskqueue.execution.TaskQueueExecutor;
 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
 import 
org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager;
 import org.apache.archiva.repository.RepositoryRegistry;
@@ -33,19 +32,14 @@ import org.apache.archiva.rest.api.model.v2.Repository;
 import org.apache.archiva.rest.api.model.v2.RepositoryStatistics;
 import org.apache.archiva.rest.api.model.v2.ScanStatus;
 import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
+import org.apache.archiva.rest.api.services.v2.ErrorKeys;
 import org.apache.archiva.rest.api.services.v2.ErrorMessage;
 import org.apache.archiva.rest.api.services.v2.RepositoryService;
-import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
-import org.apache.archiva.scheduler.indexing.IndexingArchivaTaskScheduler;
-import org.apache.archiva.scheduler.indexing.maven.ArchivaIndexingTaskExecutor;
-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.Inject;
 import javax.inject.Named;
 import javax.ws.rs.core.Response;
 import java.util.Comparator;
@@ -58,49 +52,64 @@ import java.util.stream.Collectors;
  * @author Martin Stockhammer <[email protected]>
  * @since 3.0
  */
-@Service("v2.repositoryService#rest")
+@Service( "v2.repositoryService#rest" )
 public class DefaultRepositoryService implements RepositoryService
 {
 
-    @Inject
+    final
     RepositoryRegistry repositoryRegistry;
 
-    @Inject
+    final
     RepositoryStatisticsManager repositoryStatisticsManager;
 
-    @Inject
-    @Named(value="taskQueueExecutor#indexing")
-    TaskQueueExecutor<ArtifactIndexingTask> indexingTaskExecutor;
+    private final RepositoryTaskAdministration repositoryTaskAdministration;
 
-    @Inject
-    @Named(value="taskQueueExecutor#repository-scanning")
-    TaskQueueExecutor<RepositoryTask> scanningTaskExecutor;
-
-    @Inject
-    @Named(value = "archivaTaskScheduler#repository")
-    private RepositoryArchivaTaskScheduler repositoryArchivaTaskScheduler;
-
-    @Inject
-    @Named( value = "archivaTaskScheduler#indexing" )
-    private IndexingArchivaTaskScheduler indexingArchivaTaskScheduler;
-
-    @Inject
-    private RepositoryScanner repoScanner;
+    private final RepositoryScanner repoScanner;
 
 
     private static final Logger log = LoggerFactory.getLogger( 
DefaultRepositoryService.class );
     private static final QueryHelper<org.apache.archiva.repository.Repository> 
QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} );
+
     static
     {
         QUERY_HELPER.addStringFilter( "id", 
org.apache.archiva.repository.Repository::getId );
         QUERY_HELPER.addStringFilter( "name", 
org.apache.archiva.repository.Repository::getName );
+        QUERY_HELPER.addStringFilter( "description", 
org.apache.archiva.repository.Repository::getDescription );
+        QUERY_HELPER.addStringFilter( "type", repo -> repo.getType( ).name( ) 
);
+        QUERY_HELPER.addBooleanFilter( "scanned", 
org.apache.archiva.repository.Repository::isScanned );
         QUERY_HELPER.addNullsafeFieldComparator( "id", 
org.apache.archiva.repository.Repository::getId );
         QUERY_HELPER.addNullsafeFieldComparator( "name", 
org.apache.archiva.repository.Repository::getName );
+        QUERY_HELPER.addNullsafeFieldComparator( "type", repo -> repo.getType( 
).name( ) );
+        QUERY_HELPER.addNullsafeFieldComparator( "boolean", 
org.apache.archiva.repository.Repository::isScanned );
+    }
+
+    public DefaultRepositoryService( RepositoryRegistry repositoryRegistry, 
RepositoryStatisticsManager repositoryStatisticsManager,
+                                     @Named( value = 
"repositoryTaskAdministration#default") RepositoryTaskAdministration 
repositoryTaskAdministration,
+                                     RepositoryScanner repoScanner )
+    {
+        this.repositoryRegistry = repositoryRegistry;
+        this.repositoryStatisticsManager = repositoryStatisticsManager;
+        this.repoScanner = repoScanner;
+        this.repositoryTaskAdministration = repositoryTaskAdministration;
+    }
+
+    private void handleAdminException( RepositoryAdminException e ) throws 
ArchivaRestServiceException
+    {
+        log.error( "Repository admin error: {}", e.getMessage( ), e );
+        if ( e.keyExists( ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.PREFIX + e.getKey( ), e.getParameters( ) ) );
+        }
+        else
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+        }
     }
 
+
     @Override
     public PagedResult<Repository> getRepositories( String searchTerm, Integer 
offset, Integer limit, List<String> orderBy, String order,
-                                                    String localeString) 
throws ArchivaRestServiceException
+                                                    String localeString ) 
throws ArchivaRestServiceException
     {
         final Locale locale = StringUtils.isNotEmpty( localeString ) ? 
Locale.forLanguageTag( localeString ) : Locale.getDefault( );
         boolean isAscending = QUERY_HELPER.isAscending( order );
@@ -123,7 +132,8 @@ public class DefaultRepositoryService implements 
RepositoryService
     @Override
     public RepositoryStatistics getManagedRepositoryStatistics( String 
repositoryId ) throws ArchivaRestServiceException
     {
-        if (repositoryRegistry.getManagedRepository( repositoryId )==null) {
+        if ( repositoryRegistry.getManagedRepository( repositoryId ) == null )
+        {
             throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_MANAGED_NOT_FOUND, repositoryId ), 404 );
         }
         try
@@ -142,17 +152,13 @@ public class DefaultRepositoryService implements 
RepositoryService
     {
         try
         {
-            org.apache.archiva.repository.ManagedRepository repository = 
repositoryRegistry.getManagedRepository( repositoryId );
-            ArtifactIndexingTask task =
-                new ArtifactIndexingTask( repository, null, 
ArtifactIndexingTask.Action.FINISH, repository.getIndexingContext() );
-            task.setExecuteOnEntireRepo( true );
-            task.setOnlyUpdate( !fullScan );
-            indexingArchivaTaskScheduler.queueTask( task );
-            repositoryArchivaTaskScheduler.queueTask( new RepositoryTask( 
repositoryId, fullScan ) );
+            repositoryTaskAdministration.scheduleFullScan( repositoryId );
             return Response.ok( ).build( );
-        }  catch ( TaskQueueException e ) {
-            log.error( "Could not queue the task: {}", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.TASK_QUEUE_FAILED, e.getMessage( ) ) );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            handleAdminException( e );
+            return Response.serverError( ).build( );
         }
     }
 
@@ -166,34 +172,22 @@ public class DefaultRepositoryService implements 
RepositoryService
         }
         catch ( RepositoryScannerException e )
         {
-            log.error( e.getMessage(), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_SCAN_FAILED, e.getMessage() ));
+            log.error( e.getMessage( ), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_SCAN_FAILED, e.getMessage( ) ) );
         }
     }
 
     @Override
     public ScanStatus getScanStatus( String repositoryId ) throws 
ArchivaRestServiceException
     {
-        ScanStatus status = new ScanStatus( );
         try
         {
-            RepositoryTask scanTask = scanningTaskExecutor.getCurrentTask( );
-            if ( !repositoryId.equals( scanTask.getRepositoryId( ) ) )
-            {
-                scanTask=null;
-            }
-            ArtifactIndexingTask indexTask = 
indexingTaskExecutor.getCurrentTask( );
-            if (!repositoryId.equals(indexTask.getRepository().getId())) {
-                indexTask = null;
-            }
-            status.updateScanInfo( scanTask, scanningTaskExecutor.getQueue( 
).getQueueSnapshot( ).stream( ).filter( task -> 
repositoryId.equals(task.getRepositoryId()) ).collect( Collectors.toList() ) );
-            status.updateIndexInfo( indexTask, indexingTaskExecutor.getQueue( 
).getQueueSnapshot( ).stream().filter( task -> 
repositoryId.equals(task.getRepository().getId())).collect( 
Collectors.toList()) );
-            return status;
+            return ScanStatus.of( 
repositoryTaskAdministration.getCurrentScanStatus( ) );
         }
-        catch ( TaskQueueException e )
+        catch ( RepositoryAdminException e )
         {
-            log.error( "Could not get task information: {}", e.getMessage( ), 
e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.TASK_QUEUE_FAILED, e.getMessage( ) ) );
+            handleAdminException( e );
+            return null;
         }
     }
 
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java
index 9902074..360d03e 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java
@@ -56,6 +56,7 @@ import 
org.apache.archiva.rest.api.model.v2.CacheConfiguration;
 import org.apache.archiva.rest.api.model.v2.LdapConfiguration;
 import org.apache.archiva.rest.api.model.v2.SecurityConfiguration;
 import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
+import org.apache.archiva.rest.api.services.v2.ErrorKeys;
 import org.apache.archiva.rest.api.services.v2.ErrorMessage;
 import org.apache.archiva.rest.api.services.v2.SecurityConfigurationService;
 import org.apache.commons.collections4.CollectionUtils;
@@ -87,8 +88,8 @@ import java.util.ResourceBundle;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
-import static 
org.apache.archiva.rest.services.v2.ErrorKeys.INVALID_RESULT_SET_ERROR;
-import static 
org.apache.archiva.rest.services.v2.ErrorKeys.REPOSITORY_ADMIN_ERROR;
+import static 
org.apache.archiva.rest.api.services.v2.ErrorKeys.INVALID_RESULT_SET_ERROR;
+import static 
org.apache.archiva.rest.api.services.v2.ErrorKeys.REPOSITORY_ADMIN_ERROR;
 
 /**
  * @author Martin Stockhammer <[email protected]>
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryServiceTest.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryServiceTest.java
new file mode 100644
index 0000000..0c74d3a
--- /dev/null
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryServiceTest.java
@@ -0,0 +1,162 @@
+package org.apache.archiva.rest.services.v2;
+
+/*
+ * 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 io.restassured.response.Response;
+import org.apache.archiva.components.rest.model.PagedResult;
+import org.apache.archiva.rest.api.model.v2.Repository;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestMethodOrder;
+
+import java.util.List;
+
+import static io.restassured.RestAssured.given;
+import static io.restassured.http.ContentType.JSON;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * @author Martin Stockhammer <[email protected]>
+ */
+@TestInstance( TestInstance.Lifecycle.PER_CLASS )
+@Tag( "rest-native" )
+@TestMethodOrder( MethodOrderer.Random.class )
+@DisplayName( "Native REST tests for V2 RepositoryService" )
+public class NativeRepositoryServiceTest extends AbstractNativeRestServices
+{
+    @Override
+    protected String getServicePath( )
+    {
+        return "/repositories";
+    }
+
+    @BeforeAll
+    void setup( ) throws Exception
+    {
+        super.setupNative( );
+    }
+
+    @AfterAll
+    void destroy( ) throws Exception
+    {
+        super.shutdownNative( );
+    }
+
+    @Test
+    void testGetRepositories() {
+        String token = getAdminToken( );
+            Response response = given( ).spec( getRequestSpec( token ) 
).contentType( JSON )
+                .when( )
+                .get( "" )
+                .prettyPeek()
+                .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+        PagedResult<Repository> repositoryPagedResult = response.getBody( 
).jsonPath( ).getObject( "", PagedResult.class );
+        assertEquals( 3, repositoryPagedResult.getPagination( ).getTotalCount( 
) );
+        List<Repository> data = response.getBody( ).jsonPath( ).getList( 
"data", Repository.class );
+        assertTrue( data.stream( ).anyMatch( p -> "central".equals( p.getId( ) 
) ) );
+        assertTrue( data.stream( ).anyMatch( p -> "internal".equals( p.getId( 
) ) ) );
+        assertTrue( data.stream( ).anyMatch( p -> "snapshots".equals( p.getId( 
) ) ) );
+        Repository snapshotRepo = data.stream( ).filter( p -> 
"snapshots".equals( p.getId( ) ) ).findFirst( ).get( );
+        assertEquals( "Archiva Managed Snapshot Repository", 
snapshotRepo.getName( ) );
+        assertEquals( "MAVEN", snapshotRepo.getType() );
+        assertEquals( "managed", snapshotRepo.getCharacteristic() );
+        assertEquals( "default", snapshotRepo.getLayout() );
+        assertTrue( snapshotRepo.isScanned( ) );
+        assertTrue( snapshotRepo.isIndex( ) );
+
+        Repository centralRepo = data.stream( ).filter( p -> "central".equals( 
p.getId( ) ) ).findFirst( ).get( );
+        assertEquals( "Central Repository", centralRepo.getName( ) );
+        assertEquals( "MAVEN", centralRepo.getType() );
+        assertEquals( "remote", centralRepo.getCharacteristic() );
+        assertEquals( "default", centralRepo.getLayout() );
+
+
+    }
+
+    @Test
+    void testGetFilteredRepositories() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) 
).contentType( JSON )
+            .when( )
+            .queryParam( "q", "central" )
+            .get( "" )
+            .prettyPeek()
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+        PagedResult<Repository> repositoryPagedResult = response.getBody( 
).jsonPath( ).getObject( "", PagedResult.class );
+        assertEquals( 1, repositoryPagedResult.getPagination( ).getTotalCount( 
) );
+        List<Repository> data = response.getBody( ).jsonPath( ).getList( 
"data", Repository.class );
+        assertTrue( data.stream( ).anyMatch( p -> "central".equals( p.getId( ) 
) ) );
+    }
+
+
+    @Test
+    void getStatistics() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) 
).contentType( JSON )
+            .when( )
+            .get( "managed/internal/statistics" )
+            .prettyPeek()
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+
+    }
+
+    @Test
+    void scheduleScan() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) 
).contentType( JSON )
+            .when( )
+            .post( "managed/internal/scan/schedule" )
+            .prettyPeek()
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+
+    }
+
+    @Test
+    void immediateScan() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) 
).contentType( JSON )
+            .when( )
+            .post( "managed/internal/scan/now" )
+            .prettyPeek()
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+
+    }
+
+    @Test
+    void scanStatus() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) 
).contentType( JSON )
+            .when( )
+            .get( "managed/internal/scan/status" )
+            .prettyPeek()
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+
+    }
+}

Reply via email to