import org.apache.archiva.configuration.Configuration;
import org.apache.archiva.repository.validation.RepositoryChecker;
+import org.apache.archiva.repository.validation.RepositoryValidator;
import java.util.Collection;
import java.util.Map;
*/
Collection<R> getAll();
+ /**
+ * Returns a validator that can be used to validate repository data
+ * @return a validator instance
+ */
+ RepositoryValidator<R> getValidator( );
+
/**
* Returns <code>true</code>, if the repository is registered with the given id, otherwise <code>false</code>
* @param id the repository identifier
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.UnsupportedRepositoryTypeException;
+import org.apache.archiva.repository.base.validation.CommonGroupValidator;
import org.apache.archiva.repository.event.LifecycleEvent;
import org.apache.archiva.repository.event.RepositoryEvent;
import org.apache.archiva.repository.event.RepositoryIndexEvent;
private RepositoryGroupHandler groupHandler;
private final Set<RepositoryValidator<? extends Repository>> validators;
- private final RepositoryChecker<RepositoryGroup, Map<String, List<ValidationError>>> groupChecker;
- private final RepositoryChecker<ManagedRepository, Map<String, List<ValidationError>>> managedChecker;
- private final RepositoryChecker<RemoteRepository, Map<String, List<ValidationError>>> remoteChecker;
private final ConfigurationHandler configurationHandler;
this.eventManager = new EventManager( this );
this.configurationHandler = configurationHandler;
this.validators = initValidatorList( validatorList );
- this.groupChecker = initChecker( RepositoryGroup.class );
- this.managedChecker = initChecker( ManagedRepository.class );
- this.remoteChecker = initChecker( RemoteRepository.class );
}
- private <R extends Repository> RepositoryChecker<R, Map<String, List<ValidationError>>> initChecker(Class<R> clazz) {
- return new RepositoryChecker<R, Map<String, List<ValidationError>>>( )
- {
- @Override
- public CheckedResult<R, Map<String, List<ValidationError>>> apply( R repositoryGroup )
- {
- return this.apply( repositoryGroup );
- }
-
- @Override
- public CheckedResult<R, Map<String, List<ValidationError>>> applyForUpdate( R repo )
- {
- return this.applyForUpdate( repo );
- }
- };
- }
private Set<RepositoryValidator<? extends Repository>> initValidatorList( List<RepositoryValidator<? extends Repository>> validators )
{
rwLock.writeLock( ).lock( );
try
{
- return groupHandler.putWithCheck( repositoryGroupConfiguration, this.groupChecker );
+ return groupHandler.putWithCheck( repositoryGroupConfiguration, groupHandler.getValidator() );
}
finally
{
import org.apache.archiva.repository.features.IndexCreationFeature;
import org.apache.archiva.repository.storage.StorageAsset;
import org.apache.archiva.repository.validation.RepositoryChecker;
+import org.apache.archiva.repository.validation.RepositoryValidator;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
private final Map<String, RepositoryGroup> repositoryGroups = new HashMap<>( );
+ private final RepositoryValidator<RepositoryGroup> validator;
private Path groupsDirectory;
+
/**
* Creates a new instance. All dependencies are injected on the constructor.
*
*/
public RepositoryGroupHandler( ArchivaRepositoryRegistry repositoryRegistry,
ConfigurationHandler configurationHandler,
- @Named( "mergedRemoteIndexesScheduler#default" ) MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler )
+ @Named( "mergedRemoteIndexesScheduler#default" ) MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler,
+ @Named( "repositoryValidator#common#group") RepositoryValidator<RepositoryGroup> repositoryGroupValidator
+ )
{
this.configurationHandler = configurationHandler;
this.mergedRemoteIndexesScheduler = mergedRemoteIndexesScheduler;
this.repositoryRegistry = repositoryRegistry;
+ this.validator = repositoryGroupValidator;
}
@Override
return repositoryGroups.values( );
}
+ @Override
+ public RepositoryValidator<RepositoryGroup> getValidator( )
+ {
+ return this.validator;
+ }
+
@Override
public boolean has( String id )
{
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* Exception is thrown
+ *
* @author Martin Stockhammer <martin_s@apache.org>
*/
public class ValidationException extends ArchivaRestServiceException
private List<ValidationError> validationErrors;
- public ValidationException( ) {
+ public ValidationException( )
+ {
super( DEFAULT_MESSAGE, DEFAULT_CODE );
}
- public ValidationException( int errorCode) {
+ public ValidationException( int errorCode )
+ {
super( DEFAULT_MESSAGE, errorCode );
}
- public ValidationException( List<ValidationError> errors) {
+ public ValidationException( List<ValidationError> errors )
+ {
super( DEFAULT_MESSAGE, DEFAULT_CODE );
this.validationErrors = errors;
}
- public static ValidationException of( List<org.apache.archiva.repository.validation.ValidationError> errorList ) {
+ public static ValidationException of( List<org.apache.archiva.repository.validation.ValidationError> errorList )
+ {
return new ValidationException( errorList.stream( ).map( ValidationError::of ).collect( Collectors.toList( ) ) );
}
- public static <R extends Repository> ValidationException of( ValidationResponse<R> result ) {
- if (result.isValid()) {
+ public static ValidationException of( Map<String, List<org.apache.archiva.repository.validation.ValidationError>> errorMap )
+ {
+ return new ValidationException( errorMap.entrySet( ).stream( )
+ .flatMap( v -> v.getValue( ).stream( ).map( k -> ValidationError.of(v.getKey(), k)))
+ .collect( Collectors.toList( ) ) );
+ }
+
+ public static <R extends Repository> ValidationException of( ValidationResponse<R> result )
+ {
+ if ( result.isValid( ) )
+ {
return new ValidationException( );
- } else
+ }
+ else
{
return new ValidationException( result.getResult( ).entrySet( ).stream( ).flatMap(
v -> v.getValue( ).stream( ).map( e -> ValidationError.of( v.getKey( ), e ) ) ).collect( Collectors.toList( ) ) );
public List<ValidationError> getValidationErrors( )
{
- return validationErrors==null? Collections.emptyList() : validationErrors;
+ return validationErrors == null ? Collections.emptyList( ) : validationErrors;
}
public void setValidationErrors( List<ValidationError> validationErrors )
this.validationErrors = validationErrors;
}
- public void addValidationError( ValidationError error) {
- if (this.validationErrors==null) {
+ public void addValidationError( ValidationError error )
+ {
+ if ( this.validationErrors == null )
+ {
this.validationErrors = new ArrayList<>( );
}
this.validationErrors.add( error );
public Response.Status.Family getFamily()
{
- return Response.Status.Family.SERVER_ERROR;
+ return Response.Status.Family.familyOf( e.getHttpErrorCode( ) );
}
public String getReasonPhrase()
import org.apache.archiva.configuration.Configuration;
import org.apache.archiva.configuration.IndeterminateConfigurationException;
import org.apache.archiva.configuration.RepositoryGroupConfiguration;
+import org.apache.archiva.repository.CheckedResult;
import org.apache.archiva.repository.EditableRepositoryGroup;
import org.apache.archiva.repository.RepositoryException;
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.base.ConfigurationHandler;
+import org.apache.archiva.repository.validation.ValidationError;
import org.apache.archiva.repository.validation.ValidationResponse;
+import org.apache.archiva.rest.api.model.v2.MergeConfiguration;
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 javax.ws.rs.core.UriInfo;
import java.util.Comparator;
import java.util.List;
+import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
result.setId( group.getId( ) );
result.setLocation( group.getLocation( ) );
result.setRepositories( group.getRepositories( ) );
- result.setMergedIndexPath( group.getMergeConfiguration( ).getMergedIndexPath( ) );
- result.setMergedIndexTtl( group.getMergeConfiguration( ).getMergedIndexTtlMinutes( ) );
- result.setCronExpression( group.getMergeConfiguration( ).getIndexMergeSchedule( ) );
+ MergeConfiguration mergeConfig = group.getMergeConfiguration( );
+ if (mergeConfig!=null)
+ {
+ result.setMergedIndexPath( mergeConfig.getMergedIndexPath( ) );
+ result.setMergedIndexTtl( mergeConfig.getMergedIndexTtlMinutes( ) );
+ result.setCronExpression( mergeConfig.getIndexMergeSchedule( ) );
+ }
return result;
}
}
try
{
+
RepositoryGroupConfiguration configuration = toConfig( repositoryGroup );
- Configuration config = configurationHandler.getBaseConfiguration( );
- org.apache.archiva.repository.RepositoryGroup repo = repositoryRegistry.putRepositoryGroup( configuration, config);
- if ( repo!=null )
- {
- ValidationResponse<org.apache.archiva.repository.RepositoryGroup> validationResult = repositoryRegistry.validateRepository( repo );
+ CheckedResult<org.apache.archiva.repository.RepositoryGroup, Map<String, List<ValidationError>>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration );
if ( validationResult.isValid( ) )
{
httpServletResponse.setStatus( 201 );
- configurationHandler.save( config );
- return RepositoryGroup.of( repo );
+ return RepositoryGroup.of( validationResult.getRepository() );
} else {
- throw ValidationException.of( validationResult );
+ throw ValidationException.of( validationResult.getResult() );
}
- }
- else
- {
- throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_ADD_FAILED ) );
- }
}
- catch ( RepositoryException | IndeterminateConfigurationException | RegistryException e )
+ catch ( RepositoryException e )
{
throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_ADD_FAILED ) );
}
throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND ), 404 );
}
repositoryGroup.setId( repositoryGroupId );
-
try
{
RepositoryGroupConfiguration configuration = toConfig( repositoryGroup );
- Configuration config = configurationHandler.getBaseConfiguration( );
- org.apache.archiva.repository.RepositoryGroup repo = repositoryRegistry.putRepositoryGroup( configuration, config);
- if ( repo!=null )
- {
- ValidationResponse<org.apache.archiva.repository.RepositoryGroup> validationResult = repositoryRegistry.validateRepository( repo );
+ CheckedResult<org.apache.archiva.repository.RepositoryGroup, Map<String, List<ValidationError>>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration );
if ( validationResult.isValid( ) )
{
httpServletResponse.setStatus( 201 );
- configurationHandler.save( config );
- return RepositoryGroup.of( repo );
+ return RepositoryGroup.of( validationResult.getRepository() );
} else {
- throw ValidationException.of( validationResult );
+ throw ValidationException.of( validationResult.getResult() );
}
- }
- else
- {
- log.error( "Returned repository group was null {}", repositoryGroupId );
- throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED ) );
- }
-
}
- catch ( RepositoryException | IndeterminateConfigurationException | RegistryException e )
+ catch ( RepositoryException e )
{
log.error( "Exception during repository group update: {}", e.getMessage( ), e );
throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage() ) );
Response result = given( ).spec( getAuthRequestSpecBuilder().build() )
.contentType( JSON )
.body( jsonAsMap )
- .when( ).post( "/authenticate").prettyPeek().then( ).statusCode( 200 )
+ .when( ).post( "/authenticate").then( ).statusCode( 200 )
.extract( ).response( );
- result.getBody( ).prettyPrint( );
return result.body( ).jsonPath( ).getString( "access_token" );
}
protected String getAdminToken() {
import io.restassured.response.Response;
import org.apache.archiva.components.rest.model.PagedResult;
-import org.apache.archiva.components.rest.model.PropertyEntry;
-import org.apache.archiva.rest.api.model.v2.BeanInformation;
-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.RepositoryGroup;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestMethodOrder;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static io.restassured.RestAssured.given;
import static io.restassured.http.ContentType.JSON;
-import static org.junit.jupiter.api.Assertions.*;
+import static org.easymock.EasyMock.contains;
+import static org.hamcrest.Matchers.endsWith;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* @author Martin Stockhammer <martin_s@apache.org>
}
@Test
- void testGetConfiguration() {
+ void testGetEmptyList( )
+ {
+ String token = getAdminToken( );
+ Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .get( "" )
+ .then( ).statusCode( 200 ).extract( ).response( );
+ assertNotNull( response );
+ PagedResult result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+ assertEquals( 0, result.getPagination( ).getTotalCount( ) );
+
+ }
+
+ @Test
+ void testAddGroup( )
+ {
String token = getAdminToken( );
+ try
+ {
+ Map<String, Object> jsonAsMap = new HashMap<>( );
+ jsonAsMap.put( "id", "group_001" );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
- .get( "" )
+ .body( jsonAsMap )
+ .post( "" )
.prettyPeek()
+ .then( ).statusCode( 201 ).extract( ).response( );
+ assertNotNull( response );
+ RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class );
+ assertNotNull( result );
+
+ response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .get( "" )
.then( ).statusCode( 200 ).extract( ).response( );
- assertNotNull( response );
+ assertNotNull( response );
+ PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+ assertEquals( 1, resultList.getPagination( ).getTotalCount( ) );
+ } finally
+ {
+ given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .delete( "group_001" )
+ .then( ).statusCode( 200 );
+ }
+ }
+
+ @Test
+ void testAddExistingGroup( )
+ {
+ String token = getAdminToken( );
+ try
+ {
+ Map<String, Object> jsonAsMap = new HashMap<>( );
+ jsonAsMap.put( "id", "group_001" );
+ Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .body( jsonAsMap )
+ .post( "" )
+ .then( ).statusCode( 201 ).extract( ).response( );
+ assertNotNull( response );
+ response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .redirects().follow( false )
+ .body( jsonAsMap )
+ .post( "" )
+ .prettyPeek()
+ .then( ).statusCode( 303 )
+ .assertThat()
+ .header( "Location", endsWith("group_001") ).extract( ).response( );
+ } finally
+ {
+ given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .delete( "group_001" )
+ .then( ).statusCode( 200 );
+ }
}
+ @Test
+ void testAddMultipleGroups( )
+ {
+ String token = getAdminToken( );
+ List<String> groups = new ArrayList<>( );
+ try
+ {
+ for ( int i=0; i<10; i++)
+ {
+ String groupName = String.format( "group_%03d", i );
+ groups.add( groupName );
+ Map<String, Object> jsonAsMap = new HashMap<>( );
+ jsonAsMap.put( "id", groupName );
+ Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .body( jsonAsMap )
+ .post( "" )
+ .then( ).statusCode( 201 ).extract( ).response( );
+ assertNotNull( response );
+ RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class );
+ assertNotNull( result );
+ }
+ Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .get( "" )
+ .then( ).statusCode( 200 ).extract( ).response( );
+ assertNotNull( response );
+ PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+ assertEquals( 10, resultList.getPagination( ).getTotalCount( ) );
+ } finally
+ {
+ for (String groupName : groups)
+ {
+ given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .delete( groupName )
+ .then( ).statusCode( 200 );
+ }
+ }
+ }
}
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 );
.when( )
.queryParam( "q", "central" )
.get( "" )
- .prettyPeek()
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
PagedResult<Repository> repositoryPagedResult = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.get( "managed/internal/statistics" )
- .prettyPeek()
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.post( "managed/internal/scan/schedule" )
- .prettyPeek()
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.post( "managed/internal/scan/now" )
- .prettyPeek()
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.get( "managed/internal/scan/status" )
- .prettyPeek()
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );