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