@@ -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(); | |||
} | |||
@@ -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(); | |||
} | |||
@@ -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" /> | |||
@@ -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 | |||
*/ |
@@ -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; | |||
} |
@@ -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( ); | |||
} | |||
} |
@@ -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( ); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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 ); | |||
} | |||
} |
@@ -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} |
@@ -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> | |||
@@ -166,6 +178,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> |
@@ -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 ); | |||
} | |||
} | |||
} |
@@ -26,7 +26,7 @@ import org.springframework.stereotype.Service; | |||
/** | |||
* @author Olivier Lamy | |||
*/ | |||
@Service("archivaTaskScheduler#repository") | |||
@Service("archivaTaskScheduler#mock") | |||
public class MockRepositoryArchivaTaskScheduler | |||
implements RepositoryArchivaTaskScheduler | |||
{ |
@@ -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( ) ); | |||
} | |||
} |
@@ -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> |
@@ -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; | |||
} | |||
@@ -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() ); |
@@ -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" ) |
@@ -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; | |||
} |
@@ -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 |
@@ -144,10 +144,6 @@ public interface RepositoryService | |||
throws ArchivaRestServiceException; | |||
/** | |||
* scan directories | |||
* @since 1.4-M3 | |||
*/ | |||
@Path ("managed/{id}/scan/now") | |||
@POST | |||
@Produces ({ APPLICATION_JSON }) |
@@ -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; |
@@ -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; |
@@ -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; | |||
} | |||
} | |||
@@ -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> |
@@ -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 ); | |||
} | |||
} |