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

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

commit 069783fb77d39492328e83157f2c89cfa5236dd4
Author: Martin Stockhammer <[email protected]>
AuthorDate: Tue Jan 19 20:46:30 2021 +0100

    Implementing V2 REST service
---
 .../admin/model/EntityNotFoundException.java       |   4 +
 .../admin/model/RepositoryAdminException.java      |  44 +++-
 .../archiva/admin/model/beans/RepositoryGroup.java |   2 +-
 .../admin/model/group/RepositoryGroupAdmin.java    |  15 +-
 .../admin/model/error/AdminErrors.properties       |   1 +
 .../group/DefaultRepositoryGroupAdmin.java         |  23 ++-
 .../api/services/v2/RepositoryGroupService.java    |   2 +-
 .../services/v2/DefaultRepositoryGroupService.java | 225 +++++++++++++++++----
 .../v2/DefaultSecurityConfigurationService.java    |  38 +---
 .../apache/archiva/rest/services/v2/ErrorKeys.java |   4 +
 .../src/main/resources/META-INF/spring-context.xml |   1 +
 .../v2/NativeRepositoryGroupServiceTest.java       |  85 ++++++++
 12 files changed, 353 insertions(+), 91 deletions(-)

diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/EntityNotFoundException.java
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/EntityNotFoundException.java
index 90bf82d..60f6386 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/EntityNotFoundException.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/EntityNotFoundException.java
@@ -49,6 +49,10 @@ public class EntityNotFoundException extends 
RepositoryAdminException
         return new EntityNotFoundException( message, parameters );
     }
 
+    public static EntityNotFoundException ofMessage(String message, String... 
parameters) {
+        return new EntityNotFoundException( message, parameters );
+    }
+
     public EntityNotFoundException( String s, String... parameters )
     {
         super( s );
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/RepositoryAdminException.java
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/RepositoryAdminException.java
index c684c0e..dea522c 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/RepositoryAdminException.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/RepositoryAdminException.java
@@ -26,6 +26,9 @@ import java.util.Locale;
 import java.util.ResourceBundle;
 
 /**
+ *
+ * Base exception class for the admin interfaces. Exceptions should set keys 
that allows identifying and classifying the error.
+ *
  * @author Olivier Lamy
  * @since 1.4-M1
  */
@@ -54,7 +57,18 @@ public class RepositoryAdminException
      */
     String[] parameters = new String[0];
 
+    protected static String getMessage( String key, String[] params )
+    {
+        return MessageFormat.format( bundle.getString( key ), params );
+    }
 
+    /**
+     * Tries to retrieve a message from the bundle for the given key and 
returns the
+     * exception.
+     * @param key the identifier of the error
+     * @param params parameters for translating the message
+     * @return the exception
+     */
     public static RepositoryAdminException ofKey(String key, String... params) 
{
         String message = getMessage( key, params );
         RepositoryAdminException ex = new RepositoryAdminException( message );
@@ -63,11 +77,14 @@ public class RepositoryAdminException
         return ex;
     }
 
-    protected static String getMessage( String key, String[] params )
-    {
-        return MessageFormat.format( bundle.getString( key ), params );
-    }
-
+    /**
+     * Tries to retrieve a message from the bundle for the given key and 
returns the
+     * exception.
+     * @param key the identifier of the error
+     * @param cause the exception that caused the error
+     * @param params parameters for translating the message
+     * @return the exception
+     */
     public static RepositoryAdminException ofKey(String key, Throwable cause, 
String... params) {
         String message = getMessage( key, params );
         RepositoryAdminException ex = new RepositoryAdminException( message, 
cause );
@@ -77,6 +94,14 @@ public class RepositoryAdminException
     }
 
 
+    /**
+     * Tries to retrieve a message from the bundle for the given key and the 
given field and returns the
+     * exception.
+     * @param key the identifier of the error
+     * @param fieldName the field this exception is for
+     * @param params parameters for translating the message
+     * @return the exception
+     */
     public static RepositoryAdminException ofKeyAndField(String key, String 
fieldName, String... params) {
         String message = getMessage( key, params );
         RepositoryAdminException ex = new RepositoryAdminException( message, 
fieldName );
@@ -85,6 +110,15 @@ public class RepositoryAdminException
         return ex;
     }
 
+    /**
+     * Tries to retrieve a message from the bundle for the given key and the 
given field and returns the
+     * exception.
+     * @param key the identifier of the error
+     * @param fieldName the field this exception is for
+     * @param cause the exception that caused this error
+     * @param params parameters for translating the message
+     * @return the exception
+     */
     public static RepositoryAdminException ofKeyAndField(String key, Throwable 
cause, String fieldName, String... params) {
         String message = getMessage( key, params );
         RepositoryAdminException ex = new RepositoryAdminException( message, 
cause, fieldName );
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RepositoryGroup.java
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RepositoryGroup.java
index d4c0041..7e39a3d 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RepositoryGroup.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RepositoryGroup.java
@@ -51,7 +51,7 @@ public class RepositoryGroup
     /**
      * The TTL (time to live) of the repo group's merged index.
      */
-    private int mergedIndexTtl = 30;
+    private int mergedIndexTtl = -1;
 
     /**
      * default model value is empty so none
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/group/RepositoryGroupAdmin.java
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/group/RepositoryGroupAdmin.java
index e5411fe..de1fd12 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/group/RepositoryGroupAdmin.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/group/RepositoryGroupAdmin.java
@@ -19,6 +19,7 @@ package org.apache.archiva.admin.model.group;
  */
 
 import org.apache.archiva.admin.model.AuditInformation;
+import org.apache.archiva.admin.model.EntityExistsException;
 import org.apache.archiva.admin.model.EntityNotFoundException;
 import org.apache.archiva.admin.model.RepositoryAdminException;
 import org.apache.archiva.admin.model.beans.RepositoryGroup;
@@ -28,6 +29,7 @@ import java.util.List;
 import java.util.Map;
 
 /**
+ * Methods for administering repository groups (virtual repositories)
  * @author Olivier Lamy
  * @since 1.4-M1
  */
@@ -57,8 +59,19 @@ public interface RepositoryGroupAdmin
     Boolean deleteRepositoryGroup( String repositoryGroupId, AuditInformation 
auditInformation )
         throws RepositoryAdminException;
 
+    /**
+     * Adds the given managed repository to the repository group.
+     *
+     * @param repositoryGroupId the id of the repository group
+     * @param repositoryId the id of the managed repository
+     * @param auditInformation audit information
+     * @return <code>true</code>, if the repository was added, otherwise 
<code>false</code>
+     * @throws RepositoryAdminException If an error occurred , while adding 
the group.
+     * @throws EntityNotFoundException If the repository group or the managed 
repository with the given id does not exist
+     * @throws EntityExistsException If the managed repository is already 
member of the group
+     */
     Boolean addRepositoryToGroup( String repositoryGroupId, String 
repositoryId, AuditInformation auditInformation )
-        throws RepositoryAdminException;
+        throws RepositoryAdminException, EntityNotFoundException, 
EntityExistsException;
 
     Boolean deleteRepositoryFromGroup( String repositoryGroupId, String 
repositoryId,
                                        AuditInformation auditInformation )
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/resources/org/apache/archiva/admin/model/error/AdminErrors.properties
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/resources/org/apache/archiva/admin/model/error/AdminErrors.properties
index 7a9ddf8..4addc0a 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/resources/org/apache/archiva/admin/model/error/AdminErrors.properties
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/resources/org/apache/archiva/admin/model/error/AdminErrors.properties
@@ -25,3 +25,4 @@ repository_group.merged_index_ttl.min=Merged Index TTL must 
be greater than {0}.
 repository_group.repository.not_found=The member repository with id "{0}" does 
not exist. Cannot be used in a repository group.
 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
diff --git 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java
 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java
index 3b810c7..ae6c4fd 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java
@@ -229,22 +229,22 @@ public class DefaultRepositoryGroupAdmin
         org.apache.archiva.repository.RepositoryGroup repositoryGroup = 
repositoryRegistry.getRepositoryGroup( repositoryGroupId );
         if ( repositoryGroup == null )
         {
-            throw new RepositoryAdminException(
-                    "repositoryGroup with id " + repositoryGroupId + " doesn't 
not exists so cannot add repository to it" );
+            throw EntityNotFoundException.ofMessage(
+                    "Repository group with id " + repositoryGroupId + " 
doesn't not exists so cannot add repository to it", repositoryGroupId );
         }
 
         if (!(repositoryGroup instanceof EditableRepositoryGroup)) {
-            throw new RepositoryAdminException("The repository group is not 
editable "+repositoryGroupId);
+            throw 
RepositoryAdminException.ofKey("repository_group.not_editable",repositoryGroupId);
         }
         EditableRepositoryGroup editableRepositoryGroup = 
(EditableRepositoryGroup) repositoryGroup;
         if ( editableRepositoryGroup.getRepositories().stream().anyMatch( repo 
-> repositoryId.equals(repo.getId())) )
         {
-            throw new RepositoryAdminException(
-                "repositoryGroup with id " + repositoryGroupId + " already 
contain repository with id" + repositoryId );
+            throw new EntityExistsException(
+                "Repository group with id " + repositoryGroupId + " already 
contain repository with id" + repositoryId );
         }
         org.apache.archiva.repository.ManagedRepository managedRepo = 
repositoryRegistry.getManagedRepository(repositoryId);
         if (managedRepo==null) {
-            throw new RepositoryAdminException("Repository with id 
"+repositoryId+" does not exist" );
+            throw EntityNotFoundException.ofMessage("Repository with id 
"+repositoryId+" does not exist", repositoryId );
         }
 
         editableRepositoryGroup.addRepository( managedRepo );
@@ -265,19 +265,20 @@ public class DefaultRepositoryGroupAdmin
         org.apache.archiva.repository.RepositoryGroup repositoryGroup = 
repositoryRegistry.getRepositoryGroup( repositoryGroupId );
         if ( repositoryGroup == null )
         {
-            throw new RepositoryAdminException( "repositoryGroup with id " + 
repositoryGroupId
-                                                    + " doesn't not exists so 
cannot remove repository from it" );
+            throw EntityNotFoundException.ofMessage( "Repository group with id 
" + repositoryGroupId
+                                                    + " doesn't not exists so 
cannot remove repository from it", repositoryGroupId );
         }
 
         if ( !repositoryGroup.getRepositories().stream().anyMatch( repo -> 
repositoryId.equals(repo.getId()) ) )
         {
-            throw new RepositoryAdminException(
+            throw EntityNotFoundException.ofMessage(
                 "repositoryGroup with id " + repositoryGroupId + " doesn't not 
contains repository with id"
-                    + repositoryId
+                    + repositoryId, repositoryId
             );
         }
+
         if (!(repositoryGroup instanceof EditableRepositoryGroup)) {
-            throw new RepositoryAdminException("Repository group is not 
editable " + repositoryGroupId);
+            throw 
RepositoryAdminException.ofKey("repository_group.not_editable",repositoryGroupId);
         }
         EditableRepositoryGroup editableRepositoryGroup = 
(EditableRepositoryGroup) repositoryGroup;
 
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java
index 7796d1c..08ff59e 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java
@@ -87,7 +87,7 @@ public interface RepositoryGroupService
     PagedResult<RepositoryGroup> getRepositoriesGroups(@QueryParam("q") 
@DefaultValue( "" ) String searchTerm,
                                                        @QueryParam( "offset" ) 
@DefaultValue( "0" ) Integer offset,
                                                        @QueryParam( "limit" ) 
@DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit,
-                                                       @QueryParam( "orderBy") 
@DefaultValue( "key" ) List<String> orderBy,
+                                                       @QueryParam( "orderBy") 
@DefaultValue( "id" ) List<String> orderBy,
                                                        @QueryParam("order") 
@DefaultValue( "asc" ) String order)
         throws ArchivaRestServiceException;
 
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java
index 1855ea8..e348cdc 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java
@@ -22,7 +22,6 @@ import org.apache.archiva.admin.model.EntityNotFoundException;
 import org.apache.archiva.admin.model.RepositoryAdminException;
 import org.apache.archiva.admin.model.group.RepositoryGroupAdmin;
 import org.apache.archiva.components.rest.model.PagedResult;
-import org.apache.archiva.components.rest.util.PagingHelper;
 import org.apache.archiva.components.rest.util.QueryHelper;
 import 
org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal;
 import org.apache.archiva.redback.rest.services.RedbackRequestInformation;
@@ -34,6 +33,7 @@ import 
org.apache.archiva.rest.api.services.v2.RepositoryGroupService;
 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.servlet.http.HttpServletResponse;
@@ -50,9 +50,10 @@ import java.util.stream.Collectors;
  * REST V2 Implementation for repository groups.
  *
  * @author Martin Stockhammer <[email protected]>
- * @since 3.0
  * @see RepositoryGroupService
+ * @since 3.0
  */
+@Service("v2.repositoryGroupService#rest")
 public class DefaultRepositoryGroupService implements RepositoryGroupService
 {
     @Context
@@ -63,8 +64,7 @@ public class DefaultRepositoryGroupService implements 
RepositoryGroupService
 
     private static final Logger log = LoggerFactory.getLogger( 
DefaultRepositoryGroupService.class );
 
-    private static final 
QueryHelper<org.apache.archiva.admin.model.beans.RepositoryGroup> QUERY_HELPER 
= new QueryHelper( new String[]{"id"} );
-    private static final PagingHelper PROP_PAGING_HELPER = new PagingHelper( );
+    private static final 
QueryHelper<org.apache.archiva.admin.model.beans.RepositoryGroup> QUERY_HELPER 
= new QueryHelper<>( new String[]{"id"} );
 
     @Inject
     private RepositoryGroupAdmin repositoryGroupAdmin;
@@ -77,11 +77,11 @@ public class DefaultRepositoryGroupService implements 
RepositoryGroupService
     }
 
 
-    protected AuditInformation getAuditInformation()
+    protected AuditInformation getAuditInformation( )
     {
-        RedbackRequestInformation redbackRequestInformation = 
RedbackAuthenticationThreadLocal.get();
-        User user = redbackRequestInformation == null ? null : 
redbackRequestInformation.getUser();
-        String remoteAddr = redbackRequestInformation == null ? null : 
redbackRequestInformation.getRemoteAddr();
+        RedbackRequestInformation redbackRequestInformation = 
RedbackAuthenticationThreadLocal.get( );
+        User user = redbackRequestInformation == null ? null : 
redbackRequestInformation.getUser( );
+        String remoteAddr = redbackRequestInformation == null ? null : 
redbackRequestInformation.getRemoteAddr( );
         return new AuditInformation( user, remoteAddr );
     }
 
@@ -101,8 +101,10 @@ public class DefaultRepositoryGroupService implements 
RepositoryGroupService
         catch ( RepositoryAdminException e )
         {
             log.error( "Repository admin error: {}", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage() ) );
-        } catch ( ArithmeticException e ) {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+        }
+        catch ( ArithmeticException e )
+        {
             log.error( "Could not convert total count: {}", e.getMessage( ) );
             throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.INVALID_RESULT_SET_ERROR ) );
         }
@@ -112,28 +114,34 @@ public class DefaultRepositoryGroupService implements 
RepositoryGroupService
     @Override
     public RepositoryGroup getRepositoryGroup( String repositoryGroupId ) 
throws ArchivaRestServiceException
     {
+        if ( StringUtils.isEmpty( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_NOT_EXIST, "" ), 404 );
+        }
         try
         {
             org.apache.archiva.admin.model.beans.RepositoryGroup group = 
repositoryGroupAdmin.getRepositoryGroup( repositoryGroupId );
             return RepositoryGroup.of( group );
         }
-        catch ( EntityNotFoundException e ) {
+        catch ( EntityNotFoundException e )
+        {
             throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_NOT_EXIST, repositoryGroupId ), 404 );
         }
         catch ( RepositoryAdminException e )
         {
-            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage() ));
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
         }
     }
 
-    private org.apache.archiva.admin.model.beans.RepositoryGroup toModel( 
RepositoryGroup group) {
+    private org.apache.archiva.admin.model.beans.RepositoryGroup toModel( 
RepositoryGroup group )
+    {
         org.apache.archiva.admin.model.beans.RepositoryGroup result = new 
org.apache.archiva.admin.model.beans.RepositoryGroup( );
         result.setId( group.getId( ) );
         result.setLocation( group.getLocation( ) );
         result.setRepositories( new ArrayList<>( group.getRepositories( ) ) );
-        result.setMergedIndexPath( 
group.getMergeConfiguration().getMergedIndexPath() );
-        result.setMergedIndexTtl( 
group.getMergeConfiguration().getMergedIndexTtlMinutes() );
-        result.setCronExpression( 
group.getMergeConfiguration().getIndexMergeSchedule() );
+        result.setMergedIndexPath( group.getMergeConfiguration( 
).getMergedIndexPath( ) );
+        result.setMergedIndexTtl( group.getMergeConfiguration( 
).getMergedIndexTtlMinutes( ) );
+        result.setCronExpression( group.getMergeConfiguration( 
).getIndexMergeSchedule( ) );
         return result;
     }
 
@@ -143,72 +151,203 @@ public class DefaultRepositoryGroupService implements 
RepositoryGroupService
         try
         {
             Boolean result = repositoryGroupAdmin.addRepositoryGroup( toModel( 
repositoryGroup ), getAuditInformation( ) );
-            if (result) {
+            if ( result )
+            {
                 org.apache.archiva.admin.model.beans.RepositoryGroup newGroup 
= repositoryGroupAdmin.getRepositoryGroup( repositoryGroup.getId( ) );
-                if (newGroup!=null) {
+                if ( newGroup != null )
+                {
                     return RepositoryGroup.of( newGroup );
-                } else {
+                }
+                else
+                {
                     throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_ADD_FAILED ) );
                 }
-            } else {
+            }
+            else
+            {
                 throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_ADD_FAILED ) );
             }
-        } catch ( EntityExistsException e ) {
-            httpServletResponse.setHeader( "Location", 
uriInfo.getAbsolutePathBuilder( ).path( repositoryGroup.getId() ).build( 
).toString( ) );
-            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_EXIST, repositoryGroup.getId( )), 303 );
+        }
+        catch ( EntityExistsException e )
+        {
+            httpServletResponse.setHeader( "Location", 
uriInfo.getAbsolutePathBuilder( ).path( repositoryGroup.getId( ) ).build( 
).toString( ) );
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_EXIST, repositoryGroup.getId( ) ), 303 );
         }
         catch ( RepositoryAdminException 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( ) ) );
-            }
+            return handleAdminException( e );
+        }
+    }
+
+    private RepositoryGroup 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 RepositoryGroup updateRepositoryGroup( String groupId, 
RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException
+    public RepositoryGroup updateRepositoryGroup( String repositoryGroupId, 
RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException
     {
+        if ( StringUtils.isEmpty( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_NOT_EXIST, "" ), 404 );
+        }
         org.apache.archiva.admin.model.beans.RepositoryGroup updateGroup = 
toModel( repositoryGroup );
         try
         {
-            org.apache.archiva.admin.model.beans.RepositoryGroup originGroup = 
repositoryGroupAdmin.getRepositoryGroup( groupId );
-            if ( StringUtils.isEmpty( updateGroup.getId())) {
-                updateGroup.setId( groupId );
+            org.apache.archiva.admin.model.beans.RepositoryGroup originGroup = 
repositoryGroupAdmin.getRepositoryGroup( repositoryGroupId );
+            if ( StringUtils.isEmpty( updateGroup.getId( ) ) )
+            {
+                updateGroup.setId( repositoryGroupId );
+            }
+            if ( StringUtils.isEmpty( updateGroup.getLocation( ) ) )
+            {
+                updateGroup.setLocation( originGroup.getLocation( ) );
+            }
+            if ( StringUtils.isEmpty( updateGroup.getMergedIndexPath( ) ) )
+            {
+                updateGroup.setMergedIndexPath( 
originGroup.getMergedIndexPath( ) );
             }
-            if (StringUtils.isEmpty( updateGroup.getLocation() )) {
-                updateGroup.setLocation( originGroup.getLocation() );
+            if ( updateGroup.getCronExpression( ) == null )
+            {
+                updateGroup.setCronExpression( originGroup.getCronExpression( 
) );
+            }
+            if ( updateGroup.getRepositories( ) == null || 
updateGroup.getRepositories( ).size( ) == 0 )
+            {
+                updateGroup.setRepositories( originGroup.getRepositories( ) );
             }
-            if (StringUtils.isEmpty( updateGroup.getMergedIndexPath() )) {
-                updateGroup.setMergedIndexPath( 
originGroup.getMergedIndexPath() );
+            if ( updateGroup.getMergedIndexTtl( ) <= 0 )
+            {
+                updateGroup.setMergedIndexTtl( originGroup.getMergedIndexTtl( 
) );
             }
             repositoryGroupAdmin.updateRepositoryGroup( updateGroup, 
getAuditInformation( ) );
-            return RepositoryGroup.of( 
repositoryGroupAdmin.getRepositoryGroup( groupId ) );
+            return RepositoryGroup.of( 
repositoryGroupAdmin.getRepositoryGroup( repositoryGroupId ) );
+        }
+        catch ( EntityNotFoundException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_NOT_EXIST, repositoryGroupId ), 404 );
         }
         catch ( RepositoryAdminException e )
         {
-            log.error( "Repository admin error: {}", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+            return handleAdminException( e );
         }
     }
 
     @Override
     public Response deleteRepositoryGroup( String repositoryGroupId ) throws 
ArchivaRestServiceException
     {
-        return null;
+        if ( StringUtils.isEmpty( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_NOT_EXIST, "" ), 404 );
+        }
+        try
+        {
+            Boolean deleted = repositoryGroupAdmin.deleteRepositoryGroup( 
repositoryGroupId, getAuditInformation( ) );
+            if ( !deleted )
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_DELETE_FAILED ) );
+            }
+            return Response.ok( ).build( );
+        }
+        catch ( EntityNotFoundException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_NOT_EXIST, repositoryGroupId ), 404 );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            handleAdminException( e );
+            // cannot happen:
+            return null;
+        }
     }
 
     @Override
     public RepositoryGroup addRepositoryToGroup( String repositoryGroupId, 
String repositoryId ) throws ArchivaRestServiceException
     {
-        return null;
+        if ( StringUtils.isEmpty( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_NOT_EXIST, "" ), 404 );
+        }
+        if ( StringUtils.isEmpty( repositoryId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_NOT_EXIST, "" ), 404 );
+        }
+        try
+        {
+            repositoryGroupAdmin.addRepositoryToGroup( repositoryGroupId, 
repositoryId, getAuditInformation( ) );
+            return RepositoryGroup.of( 
repositoryGroupAdmin.getRepositoryGroup( repositoryGroupId ) );
+        }
+        catch ( EntityNotFoundException e )
+        {
+            return handleNotFoundException( repositoryGroupId, repositoryId, e 
);
+        }
+        catch ( EntityExistsException e )
+        {
+            // This is thrown, if the repositoryId is already assigned to the 
group. We ignore this for the PUT action (nothing to do).
+            try
+            {
+                return RepositoryGroup.of( 
repositoryGroupAdmin.getRepositoryGroup( repositoryGroupId ) );
+            }
+            catch ( RepositoryAdminException repositoryAdminException )
+            {
+                return handleAdminException( e );
+            }
+        }
+        catch ( RepositoryAdminException e )
+        {
+            return handleAdminException( e );
+        }
     }
 
     @Override
     public RepositoryGroup deleteRepositoryFromGroup( String 
repositoryGroupId, String repositoryId ) throws 
org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException
     {
-        return null;
+        if ( StringUtils.isEmpty( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_NOT_EXIST, "" ), 404 );
+        }
+        if ( StringUtils.isEmpty( repositoryId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_NOT_EXIST, "" ), 404 );
+        }
+        try
+        {
+            repositoryGroupAdmin.deleteRepositoryFromGroup( repositoryGroupId, 
repositoryId, getAuditInformation( ) );
+            return RepositoryGroup.of( 
repositoryGroupAdmin.getRepositoryGroup( repositoryGroupId ) );
+        }
+        catch ( EntityNotFoundException e )
+        {
+            return handleNotFoundException( repositoryGroupId, repositoryId, e 
);
+        }
+        catch ( RepositoryAdminException e )
+        {
+            return handleAdminException( e );
+        }
+    }
+
+    protected RepositoryGroup handleNotFoundException( String 
repositoryGroupId, String repositoryId, EntityNotFoundException e ) throws 
ArchivaRestServiceException
+    {
+        if ( e.getParameters( ).length > 0 )
+        {
+            if ( repositoryGroupId.equals( e.getParameters( )[0] ) )
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_NOT_EXIST, repositoryGroupId ), 404 );
+            }
+            else if ( repositoryId.equals( e.getParameters( )[0] ) )
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_NOT_EXIST, repositoryGroupId ), 404 );
+            }
+        }
+        log.warn( "Entity not found but neither group nor repo set in 
exception" );
+        throw new ArchivaRestServiceException( ErrorMessage.of( 
ErrorKeys.REPOSITORY_GROUP_NOT_EXIST, repositoryGroupId ), 404 );
     }
+
+
 }
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java
index dd9a3f8..c4ab09e 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java
@@ -19,10 +19,8 @@ package org.apache.archiva.rest.services.v2;/*
 import org.apache.archiva.admin.model.RepositoryAdminException;
 import org.apache.archiva.admin.model.beans.RedbackRuntimeConfiguration;
 import org.apache.archiva.admin.model.runtime.RedbackRuntimeConfigurationAdmin;
-import org.apache.archiva.components.cache.Cache;
 import org.apache.archiva.components.rest.model.PagedResult;
 import org.apache.archiva.components.rest.model.PropertyEntry;
-import org.apache.archiva.components.rest.util.PagingHelper;
 import org.apache.archiva.components.rest.util.QueryHelper;
 import org.apache.archiva.redback.authentication.Authenticator;
 import org.apache.archiva.redback.common.ldap.connection.LdapConnection;
@@ -83,10 +81,9 @@ public class DefaultSecurityConfigurationService implements 
SecurityConfiguratio
     private static final Logger log = LoggerFactory.getLogger( 
DefaultSecurityConfigurationService.class );
 
     private static final String[] KNOWN_LDAP_CONTEXT_PROVIDERS = 
{"com.sun.jndi.ldap.LdapCtxFactory","com.ibm.jndi.LDAPCtxFactory"};
-    private List<String> availableContextProviders = new ArrayList<>( );
+    private final List<String> availableContextProviders = new ArrayList<>( );
 
-    private static final QueryHelper<PropertyEntry> PROP_QUERY_HELPER = new 
QueryHelper( new String[]{"key"} );
-    private static final PagingHelper PROP_PAGING_HELPER = new PagingHelper( );
+    private static final QueryHelper<PropertyEntry> PROP_QUERY_HELPER = new 
QueryHelper<>( new String[]{"key"} );
 
     static
     {
@@ -124,10 +121,6 @@ public class DefaultSecurityConfigurationService 
implements SecurityConfiguratio
     @Inject
     private LdapUserMapper ldapUserMapper;
 
-    @Inject
-    @Named( value = "cache#users" )
-    private Cache usersCache;
-
 
     @PostConstruct
     void init( )
@@ -215,23 +208,10 @@ public class DefaultSecurityConfigurationService 
implements SecurityConfiguratio
             boolean userManagerChanged = !CollectionUtils.isEqualCollection( 
newConfiguration.getActiveUserManagers( ), conf.getUserManagerImpls( ) );
             boolean rbacManagerChanged = !CollectionUtils.isEqualCollection( 
newConfiguration.getActiveRbacManagers( ), conf.getRbacManagerImpls( ) );
 
-            boolean ldapConfigured = false;
-            for ( String um : newConfiguration.getActiveUserManagers( ) )
-            {
-                if ( um.contains( "ldap" ) )
-                {
-                    ldapConfigured = true;
-                }
-            }
+            boolean ldapConfigured = newConfiguration.getActiveUserManagers( 
).stream( ).anyMatch( um -> um.contains( "ldap" ) );
             if ( !ldapConfigured )
             {
-                for ( String rbm : newConfiguration.getActiveRbacManagers( ) )
-                {
-                    if ( rbm.contains( "ldap" ) )
-                    {
-                        ldapConfigured = true;
-                    }
-                }
+                ldapConfigured= newConfiguration.getActiveRbacManagers( 
).stream( ).anyMatch( um -> um.contains( "ldap" ) );
             }
 
             updateConfig( newConfiguration, conf );
@@ -347,7 +327,7 @@ public class DefaultSecurityConfigurationService implements 
SecurityConfiguratio
                 .collect( Collectors.toList( ) );
             return new PagedResult<>( totalCount, offset, limit, result );
         } catch (ArithmeticException e) {
-            log.error( "The total count of the result properties is higher 
than max integer value! {}" );
+            log.error( "The total count of the result properties is higher 
than max integer value!" );
             throw new ArchivaRestServiceException( ErrorMessage.of( 
INVALID_RESULT_SET_ERROR ) );
         }
         catch ( RepositoryAdminException e )
@@ -461,7 +441,7 @@ public class DefaultSecurityConfigurationService implements 
SecurityConfiguratio
 
     }
 
-    static final Properties toProperties( Map<String, String> values )
+    static Properties toProperties( Map<String, String> values )
     {
         Properties result = new Properties( );
         for ( Map.Entry<String, String> entry : values.entrySet( ) )
@@ -471,7 +451,7 @@ public class DefaultSecurityConfigurationService implements 
SecurityConfiguratio
         return result;
     }
 
-    private static final boolean isContextFactoryAvailable(final String 
factoryClass)
+    private static boolean isContextFactoryAvailable( final String 
factoryClass)
     {
         try
         {
@@ -635,7 +615,7 @@ public class DefaultSecurityConfigurationService implements 
SecurityConfiguratio
     }
 
     @Override
-    public List<BeanInformation> getAvailableUserManagers( ) throws 
ArchivaRestServiceException
+    public List<BeanInformation> getAvailableUserManagers( )
     {
         Map<String, UserManager> beans = applicationContext.getBeansOfType( 
UserManager.class );
 
@@ -656,7 +636,7 @@ public class DefaultSecurityConfigurationService implements 
SecurityConfiguratio
     }
 
     @Override
-    public List<BeanInformation> getAvailableRbacManagers( ) throws 
ArchivaRestServiceException
+    public List<BeanInformation> getAvailableRbacManagers( )
     {
         Map<String, RBACManager> beans = applicationContext.getBeansOfType( 
RBACManager.class );
 
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/ErrorKeys.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/ErrorKeys.java
index 9f65161..a77d0e2 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/ErrorKeys.java
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/ErrorKeys.java
@@ -28,6 +28,7 @@ public interface ErrorKeys
 
     String PREFIX = "archiva.";
     String REPOSITORY_GROUP_PREFIX = PREFIX + "repository_group.";
+    String REPOSITORY_PREFIX = PREFIX + "repository.";
 
     String INVALID_RESULT_SET_ERROR = "archiva.result_set.invalid";
     String REPOSITORY_ADMIN_ERROR = "archiva.repositoryadmin.error";
@@ -49,4 +50,7 @@ public interface ErrorKeys
     String REPOSITORY_GROUP_ADD_FAILED = REPOSITORY_GROUP_PREFIX+"add.failed"  
;
     String REPOSITORY_GROUP_EXIST = REPOSITORY_GROUP_PREFIX+"exists";
 
+    String REPOSITORY_GROUP_DELETE_FAILED = REPOSITORY_GROUP_PREFIX + 
"delete.failed";
+    String REPOSITORY_NOT_EXIST = REPOSITORY_PREFIX + "notexist";
+
 }
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml
index 910fb7e..46d4d3f 100644
--- 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml
@@ -117,6 +117,7 @@
 
     <jaxrs:serviceBeans>
       <ref bean="v2.defaultSecurityConfigurationService" />
+      <ref bean="v2.repositoryGroupService#rest" />
     </jaxrs:serviceBeans>
 
     <jaxrs:features>
diff --git 
a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryGroupServiceTest.java
 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryGroupServiceTest.java
new file mode 100644
index 0000000..1e4409f
--- /dev/null
+++ 
b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryGroupServiceTest.java
@@ -0,0 +1,85 @@
+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.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.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.Arrays;
+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.*;
+
+/**
+ * @author Martin Stockhammer <[email protected]>
+ */
+@TestInstance( TestInstance.Lifecycle.PER_CLASS )
+@Tag( "rest-native" )
+@TestMethodOrder( MethodOrderer.Random.class )
+@DisplayName( "Native REST tests for V2 RepositoryGroupService" )
+public class NativeRepositoryGroupServiceTest extends 
AbstractNativeRestServices
+{
+    @Override
+    protected String getServicePath( )
+    {
+        return "/repository_groups";
+    }
+
+    @BeforeAll
+    void setup( ) throws Exception
+    {
+        super.setupNative( );
+    }
+
+    @AfterAll
+    void destroy( ) throws Exception
+    {
+        super.shutdownNative( );
+    }
+
+    @Test
+    void testGetConfiguration() {
+        String token = getAdminToken( );
+            Response response = given( ).spec( getRequestSpec( token ) 
).contentType( JSON )
+                .when( )
+                .get( "" )
+                .prettyPeek()
+                .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+    }
+
+
+
+}

Reply via email to