]> source.dussan.org Git - archiva.git/commitdiff
Refactoring - consolidating package names
authorMartin Stockhammer <martin_s@apache.org>
Sun, 19 Dec 2021 17:41:02 +0000 (18:41 +0100)
committerMartin Stockhammer <martin_s@apache.org>
Sun, 19 Dec 2021 17:41:02 +0000 (18:41 +0100)
88 files changed:
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Artifact.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ArtifactTransferRequest.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/BeanInformation.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/CacheConfiguration.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/IndexingTask.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/LdapConfiguration.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepositoryUpdate.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenRemoteRepository.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MergeConfiguration.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Repository.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryGroup.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryStatistics.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanStatus.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanTask.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/SecurityConfiguration.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ValidationError.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/ArtifactCleanupInfo.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/IndexCreationInfo.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/RemoteIndexInfo.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/StagingInfo.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestError.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestServiceException.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorMessage.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RestConfiguration.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/SecurityConfigurationService.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ValidationException.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/maven/MavenManagedRepositoryService.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/package-info.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Artifact.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ArtifactTransferRequest.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/BeanInformation.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/CacheConfiguration.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/FileInfo.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/IndexingTask.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/LdapConfiguration.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepository.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepositoryUpdate.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenRemoteRepository.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MergeConfiguration.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Repository.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryGroup.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryStatistics.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanStatus.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanTask.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/SecurityConfiguration.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ValidationError.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/ArtifactCleanupInfo.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/IndexCreationInfo.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/RemoteIndexInfo.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/StagingInfo.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestError.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestServiceException.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorKeys.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorMessage.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryGroupService.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryService.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RestConfiguration.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/SecurityConfigurationService.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ValidationException.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/maven/MavenManagedRepositoryService.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/package-info.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/resources/archiva/openapi-configuration.yaml
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/interceptors/v2/ArchivaRestServiceExceptionMapper.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/ArchivaRestServiceExceptionMapper.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultMavenManagedRepositoryService.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryGroupService.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryService.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultSecurityConfigurationService.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/AbstractNativeRestServices.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeMavenManagedRepositoryServiceTest.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryGroupServiceTest.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryServiceTest.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeSecurityConfigurationServiceTest.java [deleted file]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/AbstractNativeRestServices.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeMavenManagedRepositoryServiceTest.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryGroupServiceTest.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryServiceTest.java [new file with mode: 0644]
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeSecurityConfigurationServiceTest.java [new file with mode: 0644]

diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Artifact.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Artifact.java
deleted file mode 100644 (file)
index c8fae1e..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.apache.archiva.rest.api.model.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.swagger.v3.oas.annotations.media.Schema;
-
-import java.io.Serializable;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Schema(name="Artifact", description = "Information about artifacts")
-public class Artifact implements Serializable
-{
-    private static final long serialVersionUID = 7581578317346876555L;
-    private String name;
-
-    @Schema(name="name",description = "The name of the artifact")
-    public String getName( )
-    {
-        return name;
-    }
-
-    public void setName( String name )
-    {
-        this.name = name;
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ArtifactTransferRequest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ArtifactTransferRequest.java
deleted file mode 100644 (file)
index ce22bc4..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.apache.archiva.rest.api.model.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.swagger.v3.oas.annotations.media.Schema;
-
-import java.io.Serializable;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-public class ArtifactTransferRequest implements Serializable
-{
-    private static final long serialVersionUID = -7377281345536573342L;
-
-    private String path;
-
-    @Schema(description = "The path to the artifact")
-    public String getPath( )
-    {
-        return path;
-    }
-
-    public void setPath( String path )
-    {
-        this.path = path;
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/BeanInformation.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/BeanInformation.java
deleted file mode 100644 (file)
index b795acd..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.apache.archiva.rest.api.model.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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-import java.util.Objects;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@XmlRootElement(name="beanInformation")
-@Schema(name="BeanInformation",description = "Information about a bean instance.")
-public class BeanInformation implements Serializable
-{
-    private static final long serialVersionUID = -432385743277355987L;
-    private String id;
-    private String displayName;
-    private String descriptionKey;
-    private String defaultDescription;
-    private boolean readonly;
-
-    public BeanInformation( )
-    {
-    }
-
-    public BeanInformation( String id, String displayName, String descriptionKey, String defaultDescription, boolean readonly )
-    {
-        this.id = id;
-        this.displayName = displayName;
-        this.descriptionKey = descriptionKey;
-        this.defaultDescription = defaultDescription;
-        this.readonly = readonly;
-    }
-
-    @Schema(description = "The identifier")
-    public String getId( )
-    {
-        return id;
-    }
-
-    public void setId( String id )
-    {
-        this.id = id;
-    }
-
-    @Schema(name="display_name", description = "The display name")
-    public String getDisplayName( )
-    {
-        return displayName;
-    }
-
-    public void setDisplayName( String displayName )
-    {
-        this.displayName = displayName;
-    }
-
-    @Schema(name="description_key", description = "The translation key for the description")
-    public String getDescriptionKey( )
-    {
-        return descriptionKey;
-    }
-
-    public void setDescriptionKey( String descriptionKey )
-    {
-        this.descriptionKey = descriptionKey;
-    }
-
-    @Schema(name="default_description", description = "The description translated in the default language")
-    public String getDefaultDescription( )
-    {
-        return defaultDescription;
-    }
-
-    public void setDefaultDescription( String defaultDescription )
-    {
-        this.defaultDescription = defaultDescription;
-    }
-
-    @Schema(description = "True, if this bean cannot be removed")
-    public boolean isReadonly( )
-    {
-        return readonly;
-    }
-
-    public void setReadonly( boolean readonly )
-    {
-        this.readonly = readonly;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-        BeanInformation that = (BeanInformation) o;
-        return readonly == that.readonly && id.equals( that.id ) && Objects.equals( displayName, that.displayName ) && Objects.equals( descriptionKey, that.descriptionKey ) && Objects.equals( defaultDescription, that.defaultDescription );
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        return Objects.hash( id, displayName, descriptionKey, defaultDescription, readonly );
-    }
-
-    @Override
-    public String toString( )
-    {
-        return "BeanInformation{" +
-            "id='" + id + '\'' +
-            ", display_name='" + displayName + '\'' +
-            ", description_key='" + descriptionKey + '\'' +
-            ", default_description='" + defaultDescription + '\'' +
-            ", readonly=" + readonly +
-            '}';
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/CacheConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/CacheConfiguration.java
deleted file mode 100644 (file)
index 3538900..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.apache.archiva.rest.api.model.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.swagger.v3.oas.annotations.media.Schema;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-
-/**
- * @author Olivier Lamy
- * @author Martin Stockhammer
- * @since 3.0
- */
-@XmlRootElement( name = "cacheConfiguration" )
-@Schema(name="CacheConfiguration",description = "Cache configuration attributes")
-public class CacheConfiguration
-    implements Serializable
-{
-    private static final long serialVersionUID = 5479989049980673894L;
-    /**
-     * TimeToIdleSeconds.
-     */
-    private int timeToIdleSeconds = -1;
-
-    /**
-     * TimeToLiveSeconds.
-     */
-    private int timeToLiveSeconds = -1;
-
-    /**
-     * max elements in memory.
-     */
-    private int maxEntriesInMemory = -1;
-
-    /**
-     * max elements on disk.
-     */
-    private int maxEntriesOnDisk = -1;
-
-    public CacheConfiguration()
-    {
-        // no op
-    }
-
-    public static CacheConfiguration of( org.apache.archiva.admin.model.beans.CacheConfiguration beanConfiguration ) {
-        CacheConfiguration newConfig = new CacheConfiguration( );
-        newConfig.setMaxEntriesInMemory( beanConfiguration.getMaxElementsInMemory() );
-        newConfig.setMaxEntriesOnDisk( beanConfiguration.getMaxElementsOnDisk() );
-        newConfig.setTimeToIdleSeconds( beanConfiguration.getTimeToIdleSeconds( ) );
-        newConfig.setTimeToLiveSeconds( beanConfiguration.getTimeToLiveSeconds( ) );
-        return newConfig;
-    }
-
-    @Schema(name="time_to_idle_seconds", description = "The maximum number of seconds an element can exist in the cache without being accessed. "+
-        "The element expires at this limit and will no longer be returned from the cache.")
-    public int getTimeToIdleSeconds()
-    {
-        return timeToIdleSeconds;
-    }
-
-    public void setTimeToIdleSeconds( int timeToIdleSeconds )
-    {
-        this.timeToIdleSeconds = timeToIdleSeconds;
-    }
-
-    @Schema(name="time_to_live_seconds", description = "The maximum number of seconds an element can exist in the cache regardless of use. "+
-        "The element expires at this limit and will no longer be returned from the cache.")
-    public int getTimeToLiveSeconds()
-    {
-        return timeToLiveSeconds;
-    }
-
-    public void setTimeToLiveSeconds( int timeToLiveSeconds )
-    {
-        this.timeToLiveSeconds = timeToLiveSeconds;
-    }
-
-    @Schema(name="max_entries_in_memory", description = "The maximum cache entries to keep in memory. If the limit is reached, older entries will be evicted, or persisted on disk.")
-    public int getMaxEntriesInMemory()
-    {
-        return maxEntriesInMemory;
-    }
-
-    public void setMaxEntriesInMemory( int maxEntriesInMemory )
-    {
-        this.maxEntriesInMemory = maxEntriesInMemory;
-    }
-
-    @Schema(name="max_entries_on_disk", description = "The maximum cache entries to keep on disk. If the limit is reached, older entries will be evicted.")
-    public int getMaxEntriesOnDisk()
-    {
-        return maxEntriesOnDisk;
-    }
-
-    public void setMaxEntriesOnDisk( int maxEntriesOnDisk )
-    {
-        this.maxEntriesOnDisk = maxEntriesOnDisk;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-
-        CacheConfiguration that = (CacheConfiguration) o;
-
-        if ( timeToIdleSeconds != that.timeToIdleSeconds ) return false;
-        if ( timeToLiveSeconds != that.timeToLiveSeconds ) return false;
-        if ( maxEntriesInMemory != that.maxEntriesInMemory ) return false;
-        return maxEntriesOnDisk == that.maxEntriesOnDisk;
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        int result = timeToIdleSeconds;
-        result = 31 * result + timeToLiveSeconds;
-        result = 31 * result + maxEntriesInMemory;
-        result = 31 * result + maxEntriesOnDisk;
-        return result;
-    }
-
-    @Override
-    public String toString()
-    {
-        final StringBuilder sb = new StringBuilder();
-        sb.append( "CacheConfiguration" );
-        sb.append( "{time_to_idle_seconds=" ).append( timeToIdleSeconds );
-        sb.append( ", time_to_live_seconds=" ).append( timeToLiveSeconds );
-        sb.append( ", max_elements_in_memory=" ).append( maxEntriesInMemory );
-        sb.append( ", max_elements_on_disk=" ).append( maxEntriesOnDisk );
-        sb.append( '}' );
-        return sb.toString();
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java
deleted file mode 100644 (file)
index d5612c6..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-package org.apache.archiva.rest.api.model.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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-import org.apache.archiva.repository.storage.StorageAsset;
-
-import java.io.Serializable;
-import java.time.OffsetDateTime;
-import java.time.ZoneOffset;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Schema(name="FileInfo",description = "Information about a file stored in the repository")
-public class FileInfo implements Serializable
-{
-    private static final long serialVersionUID = 900497784542880195L;
-    private OffsetDateTime modified;
-    private String fileName;
-    private String path;
-
-    public FileInfo( )
-    {
-    }
-
-    public static FileInfo of( StorageAsset asset ) {
-        FileInfo fileInfo = new FileInfo( );
-        fileInfo.setFileName( asset.getName() );
-        fileInfo.setPath( asset.getPath() );
-        fileInfo.setModified( asset.getModificationTime( ).atOffset( ZoneOffset.UTC ) );
-        return fileInfo;
-    }
-
-                               @Schema(description = "Time when the file was last modified")
-    public OffsetDateTime getModified( )
-    {
-        return modified;
-    }
-
-    public void setModified( OffsetDateTime modified )
-    {
-        this.modified = modified;
-    }
-
-    @Schema(name="file_name", description = "Name of the file")
-    public String getFileName( )
-    {
-        return fileName;
-    }
-
-    public void setFileName( String fileName )
-    {
-        this.fileName = fileName;
-    }
-
-    @Schema(name="path", description = "Path to the file relative to the repository directory")
-    public String getPath( )
-    {
-        return path;
-    }
-
-    public void setPath( String path )
-    {
-        this.path = path;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-
-        FileInfo fileInfo = (FileInfo) o;
-
-        if ( modified != null ? !modified.equals( fileInfo.modified ) : fileInfo.modified != null ) return false;
-        if ( fileName != null ? !fileName.equals( fileInfo.fileName ) : fileInfo.fileName != null ) return false;
-        return path != null ? path.equals( fileInfo.path ) : fileInfo.path == null;
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        int result = modified != null ? modified.hashCode( ) : 0;
-        result = 31 * result + ( fileName != null ? fileName.hashCode( ) : 0 );
-        result = 31 * result + ( path != null ? path.hashCode( ) : 0 );
-        return result;
-    }
-
-    @Override
-    public String toString( )
-    {
-        final StringBuilder sb = new StringBuilder( "FileInfo{" );
-        sb.append( "modified=" ).append( modified );
-        sb.append( ", fileName='" ).append( fileName ).append( '\'' );
-        sb.append( ", path='" ).append( path ).append( '\'' );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/IndexingTask.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/IndexingTask.java
deleted file mode 100644 (file)
index b3bc509..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.apache.archiva.rest.api.model.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.swagger.v3.oas.annotations.media.Schema;
-import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
-import org.apache.archiva.scheduler.repository.model.RepositoryTask;
-
-import java.io.Serializable;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Schema(name="IndexingTask",description = "Information about indexing tasks")
-public class IndexingTask implements Serializable
-{
-    private static final long serialVersionUID = -1947200162602613310L;
-    private String repositoryId = "";
-    private boolean fullRepository;
-    private boolean updateOnly;
-    private String resource = "";
-    private boolean running = false;
-    private long maxExecutionTimeMs = 0;
-
-    public static IndexingTask of( org.apache.archiva.admin.model.beans.IndexingTask repositoryTask ) {
-        IndexingTask indexingTask = new IndexingTask( );
-        indexingTask.setFullRepository( repositoryTask.isFullScan());
-        indexingTask.setUpdateOnly( repositoryTask.isUpdateOnly() );
-        indexingTask.setResource( repositoryTask.getResource() );
-        indexingTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTimeMs() );
-        indexingTask.setRepositoryId( repositoryTask.getRepositoryId() );
-        return indexingTask;
-    }
-
-    @Schema(name="repository_id",description = "Identifier of the repository this task is running on")
-    public String getRepositoryId( )
-    {
-        return repositoryId;
-    }
-
-    public void setRepositoryId( String repositoryId )
-    {
-        this.repositoryId = repositoryId==null?"":repositoryId;
-    }
-
-    @Schema( name = "full_repository", description = "True, if this is a full repository index scan" )
-    public boolean isFullRepository( )
-    {
-        return fullRepository;
-    }
-
-    public void setFullRepository( boolean fullRepository )
-    {
-        this.fullRepository = fullRepository;
-    }
-
-    @Schema(name="update_only", description = "True, if this is only updating the index with new files")
-    public boolean isUpdateOnly( )
-    {
-        return updateOnly;
-    }
-
-    public void setUpdateOnly( boolean updateOnly )
-    {
-        this.updateOnly = updateOnly;
-    }
-
-    @Schema(name="resource",description = "The resource that should be updated, if this is not a full repo update")
-    public String getResource( )
-    {
-        return resource;
-    }
-
-    public void setResource( String resource )
-    {
-        this.resource = resource == null ? "" : resource;
-    }
-
-    @Schema(name="running", description = "True, if this task is currently running")
-    public boolean isRunning( )
-    {
-        return running;
-    }
-
-    public void setRunning( boolean running )
-    {
-        this.running = running;
-    }
-
-    @Schema(name="max_execution_time_ms",description = "Maximum task execution time in ms")
-    public long getMaxExecutionTimeMs( )
-    {
-        return maxExecutionTimeMs;
-    }
-
-    public void setMaxExecutionTimeMs( long maxExecutionTimeMs )
-    {
-        this.maxExecutionTimeMs = maxExecutionTimeMs;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-
-        IndexingTask that = (IndexingTask) o;
-
-        if ( fullRepository != that.fullRepository ) return false;
-        if ( updateOnly != that.updateOnly ) return false;
-        if ( running != that.running ) return false;
-        if ( maxExecutionTimeMs != that.maxExecutionTimeMs ) return false;
-        if ( !repositoryId.equals( that.repositoryId ) ) return false;
-        return resource.equals( that.resource );
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        int result = repositoryId.hashCode( );
-        result = 31 * result + ( fullRepository ? 1 : 0 );
-        result = 31 * result + ( updateOnly ? 1 : 0 );
-        result = 31 * result + resource.hashCode( );
-        result = 31 * result + ( running ? 1 : 0 );
-        result = 31 * result + (int) ( maxExecutionTimeMs ^ ( maxExecutionTimeMs >>> 32 ) );
-        return result;
-    }
-
-    @Override
-    public String toString( )
-    {
-        final StringBuilder sb = new StringBuilder( "IndexingTask{" );
-        sb.append( "repositoryId='" ).append( repositoryId ).append( '\'' );
-        sb.append( ", fullRepository=" ).append( fullRepository );
-        sb.append( ", updateOnly=" ).append( updateOnly );
-        sb.append( ", resource='" ).append( resource ).append( '\'' );
-        sb.append( ", running=" ).append( running );
-        sb.append( ", maxExecutionTimeMs=" ).append( maxExecutionTimeMs );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/LdapConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/LdapConfiguration.java
deleted file mode 100644 (file)
index d6d481a..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-package org.apache.archiva.rest.api.model.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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.TreeMap;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-@XmlRootElement(name="ldapConfiguration")
-@Schema(name="LdapConfiguration", description = "LDAP configuration attributes")
-public class LdapConfiguration implements Serializable
-{
-    private static final long serialVersionUID = -4736767846016398583L;
-
-    private String hostName = "";
-    private int port = 389;
-    private String baseDn = "";
-    private String groupsBaseDn = "";
-    private String bindDn = "";
-    private String bindPassword = "";
-    private String authenticationMethod = "none";
-    private String contextFactory;
-    private boolean sslEnabled = false;
-    private boolean bindAuthenticatorEnabled = true;
-    private boolean useRoleNameAsGroup = false;
-    private Map<String, String> properties = new TreeMap<>();
-    private boolean writable = false;
-    private List<String> availableContextFactories;
-
-    public LdapConfiguration( )
-    {
-    }
-
-    public static LdapConfiguration of( org.apache.archiva.admin.model.beans.LdapConfiguration ldapConfiguration ) {
-        LdapConfiguration newCfg = new LdapConfiguration( );
-        newCfg.setAuthenticationMethod( ldapConfiguration.getAuthenticationMethod( ) );
-        newCfg.setBaseDn( ldapConfiguration.getBaseDn( ) );
-        newCfg.setGroupsBaseDn( ldapConfiguration.getBaseGroupsDn() );
-        newCfg.setBindDn( ldapConfiguration.getBindDn() );
-        newCfg.setBindPassword( ldapConfiguration.getPassword() );
-        newCfg.setBindAuthenticatorEnabled( ldapConfiguration.isBindAuthenticatorEnabled() );
-        newCfg.setHostName( ldapConfiguration.getHostName( ) );
-        newCfg.setSslEnabled( ldapConfiguration.isSsl() );
-        newCfg.setContextFactory( ldapConfiguration.getContextFactory() );
-        if (ldapConfiguration.getPort()<=0) {
-            newCfg.setPort( newCfg.isSslEnabled() ? 636 : 389 );
-        } else
-        {
-            newCfg.setPort( ldapConfiguration.getPort( ) );
-        }
-        newCfg.setProperties( ldapConfiguration.getExtraProperties( ) );
-        newCfg.setWritable( ldapConfiguration.isWritable() );
-        return newCfg;
-    }
-
-    @Schema(name="host_name", description = "The hostname to use to connect to the LDAP server")
-    public String getHostName( )
-    {
-        return hostName;
-    }
-
-    public void setHostName( String hostName )
-    {
-        this.hostName = hostName==null?"":hostName;
-    }
-
-    @Schema(description = "The port to use to connect to the LDAP server")
-    public int getPort( )
-    {
-        return port;
-    }
-
-    public void setPort( int port )
-    {
-        this.port = port;
-    }
-
-    @Schema(name="context_factory",description = "The class name of the LDAP context factory")
-    public String getContextFactory( )
-    {
-        return contextFactory;
-    }
-
-    public void setContextFactory( String contextFactory )
-    {
-        this.contextFactory = contextFactory;
-    }
-
-
-    @Schema(name="ssl_enabled", description = "True, if SSL/TLS should be used for connecting the LDAP server")
-    public boolean isSslEnabled( )
-    {
-        return sslEnabled;
-    }
-
-    public void setSslEnabled( boolean sslEnabled )
-    {
-        this.sslEnabled = sslEnabled;
-    }
-
-    @Schema(name="base_dn", description = "The BASE DN used for the LDAP server")
-    public String getBaseDn( )
-    {
-        return baseDn;
-    }
-
-    public void setBaseDn( String baseDn )
-    {
-        this.baseDn = baseDn == null ? "" : baseDn;
-    }
-
-    @Schema(name="bind_dn", description = "The distinguished name of the bind user which is used to bind to the LDAP server")
-    public String getBindDn( )
-    {
-        return bindDn;
-    }
-
-    public void setBindDn( String bindDn )
-    {
-        this.bindDn = bindDn == null ? "" : bindDn;
-    }
-
-    @Schema(name="bind_password", description = "The password used to bind to the ldap server")
-    public String getBindPassword( )
-    {
-        return bindPassword;
-    }
-
-    public void setBindPassword( String bindPassword )
-    {
-        this.bindPassword = bindPassword==null?"":bindPassword;
-    }
-
-    @Schema(name="groups_base_dn", description = "The distinguished name of the base to use for searching group.")
-    public String getGroupsBaseDn( )
-    {
-        return groupsBaseDn;
-    }
-
-    public void setGroupsBaseDn( String groupsBaseDn )
-    {
-        this.groupsBaseDn = groupsBaseDn==null?"":groupsBaseDn;
-    }
-
-    @Schema(name="authentication_method", description = "The authentication method used to bind to the LDAP server (PLAINTEXT, SASL, ...)")
-    public String getAuthenticationMethod( )
-    {
-        return authenticationMethod;
-    }
-
-    public void setAuthenticationMethod( String authenticationMethod )
-    {
-        this.authenticationMethod = authenticationMethod==null?"":authenticationMethod;
-    }
-
-    @Schema(name="bind_authenticator_enabled", description = "True, if the LDAP bind authentication is used for logging in to Archiva")
-    public boolean isBindAuthenticatorEnabled( )
-    {
-        return bindAuthenticatorEnabled;
-    }
-
-    public void setBindAuthenticatorEnabled( boolean bindAuthenticatorEnabled )
-    {
-        this.bindAuthenticatorEnabled = bindAuthenticatorEnabled;
-    }
-
-    @Schema(name="user_role_name_as_group", description = "True, if the archiva role name is also the LDAP group name")
-    public boolean isUseRoleNameAsGroup( )
-    {
-        return useRoleNameAsGroup;
-    }
-
-    public void setUseRoleNameAsGroup( boolean useRoleNameAsGroup )
-    {
-        this.useRoleNameAsGroup = useRoleNameAsGroup;
-    }
-
-    @Schema(description = "LDAP ConnectionFactory environment properties")
-    public Map<String, String> getProperties( )
-    {
-        return properties;
-    }
-
-    public void setProperties( Map<String, String> properties )
-    {
-        this.properties = new TreeMap<>( properties  );
-    }
-
-    public void addProperty(String key, String value) {
-        this.properties.put( key, value );
-    }
-
-    @Schema(description = "True, if attributes in the the LDAP server can be edited by Archiva")
-    public boolean isWritable( )
-    {
-        return writable;
-    }
-
-    public void setWritable( boolean writable )
-    {
-        this.writable = writable;
-    }
-
-    @Schema(name="available_context_factories", description = "The LDAP context factories that are known and available")
-    public List<String> getAvailableContextFactories( )
-    {
-        return availableContextFactories;
-    }
-
-    public void setAvailableContextFactories( List<String> availableContextFactories )
-    {
-        this.availableContextFactories = new ArrayList<>( availableContextFactories );
-    }
-
-    public void addAvailableContextFactory(String contextFactory) {
-        if (!this.availableContextFactories.contains( contextFactory ) ) {
-            this.availableContextFactories.add( contextFactory );
-        }
-    }
-
-
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-
-        LdapConfiguration that = (LdapConfiguration) o;
-
-        if ( port != that.port ) return false;
-        if ( sslEnabled != that.sslEnabled ) return false;
-        if ( bindAuthenticatorEnabled != that.bindAuthenticatorEnabled ) return false;
-        if ( useRoleNameAsGroup != that.useRoleNameAsGroup ) return false;
-        if ( writable != that.writable ) return false;
-        if ( !Objects.equals( hostName, that.hostName ) ) return false;
-        if ( !Objects.equals( baseDn, that.baseDn ) ) return false;
-        if ( !Objects.equals( bindDn, that.bindDn ) ) return false;
-        if ( !Objects.equals( groupsBaseDn, that.groupsBaseDn ) )
-            return false;
-        if ( !Objects.equals( bindPassword, that.bindPassword ) ) return false;
-        if ( !Objects.equals( authenticationMethod, that.authenticationMethod ) )
-            return false;
-        return properties.equals( that.properties );
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        int result = hostName != null ? hostName.hashCode( ) : 0;
-        result = 31 * result + port;
-        result = 31 * result + ( sslEnabled ? 1 : 0 );
-        result = 31 * result + ( baseDn != null ? baseDn.hashCode( ) : 0 );
-        result = 31 * result + ( bindDn != null ? bindDn.hashCode( ) : 0 );
-        result = 31 * result + ( groupsBaseDn != null ? groupsBaseDn.hashCode( ) : 0 );
-        result = 31 * result + ( bindPassword != null ? bindPassword.hashCode( ) : 0 );
-        result = 31 * result + ( authenticationMethod != null ? authenticationMethod.hashCode( ) : 0 );
-        result = 31 * result + ( bindAuthenticatorEnabled ? 1 : 0 );
-        result = 31 * result + ( useRoleNameAsGroup ? 1 : 0 );
-        result = 31 * result + properties.hashCode( );
-        result = 31 * result + ( writable ? 1 : 0 );
-        return result;
-    }
-
-    @SuppressWarnings( "StringBufferReplaceableByString" )
-    @Override
-    public String toString( )
-    {
-        final StringBuilder sb = new StringBuilder( "LdapConfiguration{" );
-        sb.append( "host_name='" ).append( hostName ).append( '\'' );
-        sb.append( ", port=" ).append( port );
-        sb.append( ", ssl_enabled=" ).append( sslEnabled );
-        sb.append( ", base_dn='" ).append( baseDn ).append( '\'' );
-        sb.append( ", groups_base_dn='" ).append( groupsBaseDn ).append( '\'' );
-        sb.append( ", bind_dn='" ).append( bindDn ).append( '\'' );
-        sb.append( ", bind_password='" ).append( bindPassword ).append( '\'' );
-        sb.append( ", authentication_method='" ).append( authenticationMethod ).append( '\'' );
-        sb.append( ", bind_authenticator_enabled=" ).append( bindAuthenticatorEnabled );
-        sb.append( ", use_role_name_as_group=" ).append( useRoleNameAsGroup );
-        sb.append( ", properties=" ).append( properties );
-        sb.append( ", writable=" ).append( writable );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java
deleted file mode 100644 (file)
index 99455f1..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-package org.apache.archiva.rest.api.model.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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-import org.apache.archiva.repository.ManagedRepository;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.features.ArtifactCleanupFeature;
-import org.apache.archiva.repository.features.IndexCreationFeature;
-import org.apache.archiva.repository.features.StagingRepositoryFeature;
-
-import java.time.Period;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Schema(name="MavenManagedRepository",description = "A managed repository stores artifacts locally")
-public class MavenManagedRepository extends Repository
-{
-    private static final long serialVersionUID = -6853748886201905029L;
-
-    boolean blocksRedeployments;
-    List<String> releaseSchemes = new ArrayList<>(  );
-    boolean deleteSnapshotsOfRelease = false;
-    private Period retentionPeriod;
-    private int retentionCount;
-    private String indexPath;
-    private String packedIndexPath;
-    private boolean skipPackedIndexCreation;
-    private boolean hasStagingRepository;
-    private String stagingRepository;
-
-
-    public MavenManagedRepository( )
-    {
-        super.setCharacteristic( Repository.CHARACTERISTIC_MANAGED );
-        super.setType( RepositoryType.MAVEN.name( ) );
-    }
-
-    protected static void update(MavenManagedRepository repo, ManagedRepository beanRepo) {
-        repo.setDescription( beanRepo.getDescription() );
-        repo.setId( beanRepo.getId() );
-        repo.setIndex( true );
-        repo.setLayout( beanRepo.getLayout() );
-        repo.setBlocksRedeployments( beanRepo.blocksRedeployments() );
-        repo.setReleaseSchemes( beanRepo.getActiveReleaseSchemes().stream().map( Objects::toString).collect( Collectors.toList()) );
-        repo.setLocation( beanRepo.getLocation().toString() );
-        repo.setName( beanRepo.getName());
-        repo.setScanned( beanRepo.isScanned() );
-        repo.setSchedulingDefinition( beanRepo.getSchedulingDefinition() );
-        ArtifactCleanupFeature artifactCleanupFeature = beanRepo.getFeature( ArtifactCleanupFeature.class ).get( );
-        repo.setDeleteSnapshotsOfRelease( artifactCleanupFeature.isDeleteReleasedSnapshots());
-        repo.setRetentionCount( artifactCleanupFeature.getRetentionCount());
-        repo.setRetentionPeriod( artifactCleanupFeature.getRetentionPeriod() );
-        IndexCreationFeature icf = beanRepo.getFeature( IndexCreationFeature.class ).get( );
-        repo.setIndex( icf.hasIndex( ) );
-        repo.setIndexPath( icf.getIndexPath( ).getPath( ) );
-        repo.setPackedIndexPath( icf.getPackedIndexPath( ).getPath( ) );
-        repo.setSkipPackedIndexCreation( icf.isSkipPackedIndexCreation() );
-        StagingRepositoryFeature srf = beanRepo.getFeature( StagingRepositoryFeature.class ).get( );
-        repo.setHasStagingRepository( srf.isStageRepoNeeded( ) );
-        repo.setStagingRepository( srf.getStagingRepository()!=null?srf.getStagingRepository().getId():"" );
-    }
-
-    public static MavenManagedRepository of( ManagedRepository beanRepo ) {
-        MavenManagedRepository repo = new MavenManagedRepository( );
-        update( repo, beanRepo );
-        return repo;
-    }
-
-    @Schema(name="blocks_redeployments",description = "True, if redeployments to this repository are not allowed")
-    public boolean isBlocksRedeployments( )
-    {
-        return blocksRedeployments;
-    }
-
-    public void setBlocksRedeployments( boolean blocksRedeployments )
-    {
-        this.blocksRedeployments = blocksRedeployments;
-    }
-
-    @Schema(name="release_schemes", description = "The release schemes this repository is used for (e.g. RELEASE, SNAPSHOT)")
-    public List<String> getReleaseSchemes( )
-    {
-        return releaseSchemes;
-    }
-
-    public void setReleaseSchemes( List<String> releaseSchemes )
-    {
-        this.releaseSchemes = new ArrayList<>( releaseSchemes );
-    }
-
-    public void addReleaseScheme(String scheme) {
-        if (!this.releaseSchemes.contains( scheme ))
-        {
-            this.releaseSchemes.add( scheme );
-        }
-    }
-
-    @Schema(name="delete_snaphots_of_release", description = "True, if snapshots are deleted, after a version is released")
-    public boolean isDeleteSnapshotsOfRelease( )
-    {
-        return deleteSnapshotsOfRelease;
-    }
-
-    public void setDeleteSnapshotsOfRelease( boolean deleteSnapshotsOfRelease )
-    {
-        this.deleteSnapshotsOfRelease = deleteSnapshotsOfRelease;
-    }
-
-    @Schema(name="retention_period", description = "The period after which snapshots are deleted.")
-    public Period getRetentionPeriod( )
-    {
-        return retentionPeriod;
-    }
-
-    public void setRetentionPeriod( Period retentionPeriod )
-    {
-        this.retentionPeriod = retentionPeriod;
-    }
-
-    @Schema(name="retention_count", description = "Number of snapshot artifacts to keep.")
-    public int getRetentionCount( )
-    {
-        return retentionCount;
-    }
-
-    public void setRetentionCount( int retentionCount )
-    {
-        this.retentionCount = retentionCount;
-    }
-
-    @Schema( name = "index_path", description = "Path to the directory that contains the index, relative to the repository base directory" )
-    public String getIndexPath( )
-    {
-        return indexPath;
-    }
-
-    public void setIndexPath( String indexPath )
-    {
-        this.indexPath = indexPath;
-    }
-
-    @Schema( name = "packed_index_path", description = "Path to the directory that contains the packed index, relative to the repository base directory" )
-    public String getPackedIndexPath( )
-    {
-        return packedIndexPath;
-    }
-
-    public void setPackedIndexPath( String packedIndexPath )
-    {
-        this.packedIndexPath = packedIndexPath;
-    }
-
-    @Schema(name="skip_packed_index_creation", description = "True, if packed index is not created during index update")
-    public boolean isSkipPackedIndexCreation( )
-    {
-        return skipPackedIndexCreation;
-    }
-
-    public void setSkipPackedIndexCreation( boolean skipPackedIndexCreation )
-    {
-        this.skipPackedIndexCreation = skipPackedIndexCreation;
-    }
-
-    @Schema(name="has_staging_repository", description = "True, if this repository has a staging repository assigned")
-    public boolean isHasStagingRepository( )
-    {
-        return hasStagingRepository;
-    }
-
-    public void setHasStagingRepository( boolean hasStagingRepository )
-    {
-        this.hasStagingRepository = hasStagingRepository;
-    }
-
-    @Schema(name="staging_repository", description = "The id of the assigned staging repository")
-    public String getStagingRepository( )
-    {
-        return stagingRepository;
-    }
-
-    public void setStagingRepository( String stagingRepository )
-    {
-        this.stagingRepository = stagingRepository;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-        if ( !super.equals( o ) ) return false;
-
-        MavenManagedRepository that = (MavenManagedRepository) o;
-
-        if ( blocksRedeployments != that.blocksRedeployments ) return false;
-        return releaseSchemes != null ? releaseSchemes.equals( that.releaseSchemes ) : that.releaseSchemes == null;
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        int result = super.hashCode( );
-        result = 31 * result + ( blocksRedeployments ? 1 : 0 );
-        result = 31 * result + ( releaseSchemes != null ? releaseSchemes.hashCode( ) : 0 );
-        return result;
-    }
-
-    @Override
-    public String toString( )
-    {
-        final StringBuilder sb = new StringBuilder( "ManagedRepository{" );
-        sb.append( "blocksRedeployments=" ).append( blocksRedeployments );
-        sb.append( ", releaseSchemes=" ).append( releaseSchemes );
-        sb.append( ", id='" ).append( id ).append( '\'' );
-        sb.append( ", name='" ).append( name ).append( '\'' );
-        sb.append( ", description='" ).append( description ).append( '\'' );
-        sb.append( ", type='" ).append( type ).append( '\'' );
-        sb.append( ", location='" ).append( location ).append( '\'' );
-        sb.append( ", scanned=" ).append( scanned );
-        sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' );
-        sb.append( ", index=" ).append( index );
-        sb.append( ", layout='" ).append( layout ).append( '\'' );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepositoryUpdate.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepositoryUpdate.java
deleted file mode 100644 (file)
index 32809f6..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.apache.archiva.rest.api.model.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 org.apache.archiva.repository.ManagedRepository;
-
-import java.io.Serializable;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-public class MavenManagedRepositoryUpdate extends MavenManagedRepository implements Serializable
-{
-    private static final long serialVersionUID = -9181643343284109862L;
-    private boolean resetStats = false;
-
-    public static MavenManagedRepositoryUpdate of( ManagedRepository repository ) {
-        MavenManagedRepositoryUpdate repo = new MavenManagedRepositoryUpdate( );
-        update( repo, repository );
-        return repo;
-    }
-
-    public boolean isResetStats( )
-    {
-        return resetStats;
-    }
-
-    public void setResetStats( boolean resetStats )
-    {
-        this.resetStats = resetStats;
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenRemoteRepository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenRemoteRepository.java
deleted file mode 100644 (file)
index 3f05fb4..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-package org.apache.archiva.rest.api.model.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.swagger.v3.oas.annotations.media.Schema;
-
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-@Schema(name="MavenRemoteRepository",description = "A remote repository definition is used to pull artifacts from other repositories")
-public class MavenRemoteRepository extends Repository
-{
-    private static final long serialVersionUID = 5625043398766480265L;
-    String loginUser;
-    String loginPassword;
-    String checkPath;
-    Map<String,String> extraParameters = new TreeMap<>(  );
-    Map<String,String> requestHeader = new TreeMap<>(  );
-    long timeoutMs;
-
-    @Schema(name="login_user",description = "Username for login to the remote repository")
-    public String getLoginUser( )
-    {
-        return loginUser;
-    }
-
-    public void setLoginUser( String loginUser )
-    {
-        this.loginUser = loginUser;
-    }
-
-    @Schema(name="login_password",description = "Password for connecting to the remote repository")
-    public String getLoginPassword( )
-    {
-        return loginPassword;
-    }
-
-    public void setLoginPassword( String loginPassword )
-    {
-        this.loginPassword = loginPassword;
-    }
-
-    @Schema(name="check_path",description = "Path relative to the repository URL that is used to check of availability of the remote repository.")
-    public String getCheckPath( )
-    {
-        return checkPath;
-    }
-
-    public void setCheckPath( String checkPath )
-    {
-        this.checkPath = checkPath;
-    }
-
-    @Schema(name="extra_parameters", description = "Key-Value map with extra parameters sent to the remote repository")
-    public Map<String, String> getExtraParameters( )
-    {
-        return extraParameters;
-    }
-
-    public void setExtraParameters( Map<String, String> extraParameters )
-    {
-        this.extraParameters = new TreeMap<>( extraParameters );
-    }
-
-    public void addExtraParameter(String key, String value) {
-        this.extraParameters.put( key, value );
-    }
-
-    @Schema(name="request_header",description = "Key-Value map with request headers that are sent to the remote repository")
-    public Map<String, String> getRequestHeader( )
-    {
-        return requestHeader;
-    }
-
-    public void setRequestHeader( Map<String, String> requestHeader )
-    {
-        this.requestHeader = new TreeMap<>( requestHeader );
-    }
-
-    public void addRequestHeader(String headerName, String headerValue) {
-        this.requestHeader.put( headerName, headerValue );
-    }
-
-    @Schema(name="timeout_ms", description = "The time in milliseconds after that a request to the remote repository is aborted")
-    public long getTimeoutMs( )
-    {
-        return timeoutMs;
-    }
-
-    public void setTimeoutMs( long timeoutMs )
-    {
-        this.timeoutMs = timeoutMs;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-        if ( !super.equals( o ) ) return false;
-
-        MavenRemoteRepository that = (MavenRemoteRepository) o;
-
-        if ( timeoutMs != that.timeoutMs ) return false;
-        if ( loginUser != null ? !loginUser.equals( that.loginUser ) : that.loginUser != null ) return false;
-        if ( loginPassword != null ? !loginPassword.equals( that.loginPassword ) : that.loginPassword != null )
-            return false;
-        if ( checkPath != null ? !checkPath.equals( that.checkPath ) : that.checkPath != null ) return false;
-        if ( extraParameters != null ? !extraParameters.equals( that.extraParameters ) : that.extraParameters != null )
-            return false;
-        return requestHeader != null ? requestHeader.equals( that.requestHeader ) : that.requestHeader == null;
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        int result = super.hashCode( );
-        result = 31 * result + ( loginUser != null ? loginUser.hashCode( ) : 0 );
-        result = 31 * result + ( loginPassword != null ? loginPassword.hashCode( ) : 0 );
-        result = 31 * result + ( checkPath != null ? checkPath.hashCode( ) : 0 );
-        result = 31 * result + ( extraParameters != null ? extraParameters.hashCode( ) : 0 );
-        result = 31 * result + ( requestHeader != null ? requestHeader.hashCode( ) : 0 );
-        result = 31 * result + (int) ( timeoutMs ^ ( timeoutMs >>> 32 ) );
-        return result;
-    }
-
-    @Override
-    public String toString( )
-    {
-        final StringBuilder sb = new StringBuilder( "RemoteRepository{" );
-        sb.append( "loginUser='" ).append( loginUser ).append( '\'' );
-        sb.append( ", loginPassword='" ).append( loginPassword ).append( '\'' );
-        sb.append( ", checkPath='" ).append( checkPath ).append( '\'' );
-        sb.append( ", extraParameters=" ).append( extraParameters );
-        sb.append( ", requestHeader=" ).append( requestHeader );
-        sb.append( ", timeOut=" ).append( timeoutMs );
-        sb.append( ", id='" ).append( id ).append( '\'' );
-        sb.append( ", name='" ).append( name ).append( '\'' );
-        sb.append( ", description='" ).append( description ).append( '\'' );
-        sb.append( ", type='" ).append( type ).append( '\'' );
-        sb.append( ", location='" ).append( location ).append( '\'' );
-        sb.append( ", scanned=" ).append( scanned );
-        sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' );
-        sb.append( ", index=" ).append( index );
-        sb.append( ", layout='" ).append( layout ).append( '\'' );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MergeConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MergeConfiguration.java
deleted file mode 100644 (file)
index 95a286b..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-package org.apache.archiva.rest.api.model.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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-import java.util.Objects;
-
-import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
-
-/**
- * Index merge configuration.
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-@XmlRootElement(name="mergeConfiguration")
-@Schema(name="MergeConfiguration", description = "Configuration settings for index merge of remote repositories.")
-public class MergeConfiguration implements Serializable
-{
-    private static final long serialVersionUID = -3629274059574459133L;
-
-    private String mergedIndexPath = DEFAULT_INDEX_PATH;
-    private int mergedIndexTtlMinutes = 30;
-    private String indexMergeSchedule = "";
-
-    @Schema(name="merged_index_path", description = "The path where the merged index is stored. The path is relative to the repository directory of the group.")
-    public String getMergedIndexPath( )
-    {
-        return mergedIndexPath;
-    }
-
-    public void setMergedIndexPath( String mergedIndexPath )
-    {
-        this.mergedIndexPath = mergedIndexPath;
-    }
-
-    @Schema(name="merged_index_ttl_minutes", description = "The Time to Life of the merged index in minutes.")
-    public int getMergedIndexTtlMinutes( )
-    {
-        return mergedIndexTtlMinutes;
-    }
-
-    public void setMergedIndexTtlMinutes( int mergedIndexTtlMinutes )
-    {
-        this.mergedIndexTtlMinutes = mergedIndexTtlMinutes;
-    }
-
-    @Schema(name="index_merge_schedule", description = "Cron expression that defines the times/intervals for index merging.")
-    public String getIndexMergeSchedule( )
-    {
-        return indexMergeSchedule;
-    }
-
-    public void setIndexMergeSchedule( String indexMergeSchedule )
-    {
-        this.indexMergeSchedule = indexMergeSchedule;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-
-        MergeConfiguration that = (MergeConfiguration) o;
-
-        if ( mergedIndexTtlMinutes != that.mergedIndexTtlMinutes ) return false;
-        if ( !Objects.equals( mergedIndexPath, that.mergedIndexPath ) )
-            return false;
-        return Objects.equals( indexMergeSchedule, that.indexMergeSchedule );
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        int result = mergedIndexPath != null ? mergedIndexPath.hashCode( ) : 0;
-        result = 31 * result + mergedIndexTtlMinutes;
-        result = 31 * result + ( indexMergeSchedule != null ? indexMergeSchedule.hashCode( ) : 0 );
-        return result;
-    }
-
-    @SuppressWarnings( "StringBufferReplaceableByString" )
-    @Override
-    public String toString( )
-    {
-        final StringBuilder sb = new StringBuilder( "MergeConfiguration{" );
-        sb.append( "mergedIndexPath='" ).append( mergedIndexPath ).append( '\'' );
-        sb.append( ", mergedIndexTtlMinutes=" ).append( mergedIndexTtlMinutes );
-        sb.append( ", indexMergeSchedule='" ).append( indexMergeSchedule ).append( '\'' );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Repository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Repository.java
deleted file mode 100644 (file)
index 04f77b9..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-package org.apache.archiva.rest.api.model.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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-import org.apache.archiva.repository.ManagedRepository;
-import org.apache.archiva.repository.RemoteRepository;
-
-import java.io.Serializable;
-import java.util.Locale;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-@Schema(description = "Repository data")
-public class Repository implements Serializable
-{
-    private static final long serialVersionUID = -4741025877287175182L;
-
-    public static final String CHARACTERISTIC_MANAGED = "managed";
-    public static final String CHARACTERISTIC_REMOTE = "remote";
-    public static final String CHARACTERISTIC_UNKNOWN = "unknown";
-
-    protected String id;
-    protected String name;
-    protected String description;
-    protected String type;
-    protected String characteristic;
-    protected String location;
-    protected boolean scanned;
-    protected String schedulingDefinition;
-    protected boolean index;
-    protected String layout;
-
-    public Repository( )
-    {
-    }
-
-    public static Repository of( org.apache.archiva.repository.Repository repository ) {
-        Repository newRepo = new Repository( );
-        newRepo.setId( repository.getId() );
-        newRepo.setName( repository.getName( ) );
-        newRepo.setDescription( repository.getDescription( ) );
-        newRepo.setLocation( repository.getLocation().toASCIIString() );
-        newRepo.setIndex( repository.hasIndex() );
-        newRepo.setLayout( repository.getLayout() );
-        newRepo.setType( repository.getType().name() );
-        newRepo.setScanned( repository.isScanned() );
-        newRepo.setSchedulingDefinition( repository.getSchedulingDefinition() );
-        if (repository instanceof RemoteRepository ) {
-            newRepo.setCharacteristic( CHARACTERISTIC_REMOTE );
-        } else if (repository instanceof ManagedRepository ) {
-            newRepo.setCharacteristic( CHARACTERISTIC_MANAGED );
-        } else {
-            newRepo.setCharacteristic( CHARACTERISTIC_UNKNOWN );
-        }
-        return newRepo;
-    }
-
-    public static Repository of( org.apache.archiva.repository.Repository repository, Locale locale ) {
-        Locale myLocale;
-        if (locale==null) {
-            myLocale = Locale.getDefault( );
-        } 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( repoName );
-        newRepo.setDescription( description );
-        newRepo.setLocation( repository.getLocation().toASCIIString() );
-        newRepo.setIndex( repository.hasIndex() );
-        newRepo.setLayout( repository.getLayout() );
-        newRepo.setType( repository.getType().name() );
-        newRepo.setScanned( repository.isScanned() );
-        newRepo.setSchedulingDefinition( repository.getSchedulingDefinition() );
-        if (repository instanceof RemoteRepository ) {
-            newRepo.setCharacteristic( CHARACTERISTIC_REMOTE );
-        } else if (repository instanceof ManagedRepository ) {
-            newRepo.setCharacteristic( CHARACTERISTIC_MANAGED );
-        } else {
-            newRepo.setCharacteristic( CHARACTERISTIC_UNKNOWN );
-        }
-        return newRepo;
-    }
-
-    @Schema(description = "Category of the repository. Either 'managed' or 'remote'.")
-    public String getCharacteristic( )
-    {
-        return characteristic;
-    }
-
-    public void setCharacteristic( String characteristic )
-    {
-        this.characteristic = characteristic;
-    }
-
-    @Schema(description = "Unique identifier of the repository")
-    public String getId( )
-    {
-        return id;
-    }
-
-    public void setId( String id )
-    {
-        this.id = id;
-    }
-
-    @Schema(description = "Display name of the repository")
-    public String getName( )
-    {
-        return name;
-    }
-
-    public void setName( String name )
-    {
-        this.name = name;
-    }
-
-    @Schema(description = "Description of the repository")
-    public String getDescription( )
-    {
-        return description;
-    }
-
-    public void setDescription( String description )
-    {
-        this.description = description;
-    }
-
-    @Schema(description = "Repository type")
-    public String getType( )
-    {
-        return type;
-    }
-
-    public void setType( String type )
-    {
-        this.type = type;
-    }
-
-    @Schema(description = "The location, where the repository data can be found")
-    public String getLocation( )
-    {
-        return location;
-    }
-
-    public void setLocation( String location )
-    {
-        this.location = location;
-    }
-
-    @Schema(description = "True, if this repository is scanned regularly")
-    public boolean isScanned( )
-    {
-        return scanned;
-    }
-
-    public void setScanned( boolean scanned )
-    {
-        this.scanned = scanned;
-    }
-
-    @Schema(name="scheduling_definition",description = "Definition of regular scheduled scan")
-    public String getSchedulingDefinition( )
-    {
-        return schedulingDefinition;
-    }
-
-    public void setSchedulingDefinition( String schedulingDefinition )
-    {
-        this.schedulingDefinition = schedulingDefinition;
-    }
-
-    @Schema(description = "True, if this is a indexed repository")
-    public boolean isIndex( )
-    {
-        return index;
-    }
-
-    public void setIndex( boolean index )
-    {
-        this.index = index;
-    }
-
-    @Schema(description = "Layout type is implementation specific")
-    public String getLayout( )
-    {
-        return layout;
-    }
-
-    public void setLayout( String layout )
-    {
-        this.layout = layout;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-
-        Repository that = (Repository) o;
-
-        if ( scanned != that.scanned ) return false;
-        if ( index != that.index ) return false;
-        if ( id != null ? !id.equals( that.id ) : that.id != null ) return false;
-        if ( name != null ? !name.equals( that.name ) : that.name != null ) return false;
-        if ( description != null ? !description.equals( that.description ) : that.description != null ) return false;
-        if ( type != null ? !type.equals( that.type ) : that.type != null ) return false;
-        if ( location != null ? !location.equals( that.location ) : that.location != null ) return false;
-        if ( schedulingDefinition != null ? !schedulingDefinition.equals( that.schedulingDefinition ) : that.schedulingDefinition != null )
-            return false;
-        return layout != null ? layout.equals( that.layout ) : that.layout == null;
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        int result = id != null ? id.hashCode( ) : 0;
-        result = 31 * result + ( name != null ? name.hashCode( ) : 0 );
-        result = 31 * result + ( description != null ? description.hashCode( ) : 0 );
-        result = 31 * result + ( type != null ? type.hashCode( ) : 0 );
-        result = 31 * result + ( location != null ? location.hashCode( ) : 0 );
-        result = 31 * result + ( scanned ? 1 : 0 );
-        result = 31 * result + ( schedulingDefinition != null ? schedulingDefinition.hashCode( ) : 0 );
-        result = 31 * result + ( index ? 1 : 0 );
-        result = 31 * result + ( layout != null ? layout.hashCode( ) : 0 );
-        return result;
-    }
-
-    @Override
-    public String toString( )
-    {
-        final StringBuilder sb = new StringBuilder( "Repository{" );
-        sb.append( "id='" ).append( id ).append( '\'' );
-        sb.append( ", name='" ).append( name ).append( '\'' );
-        sb.append( ", description='" ).append( description ).append( '\'' );
-        sb.append( ", type='" ).append( type ).append( '\'' );
-        sb.append( ", location='" ).append( location ).append( '\'' );
-        sb.append( ", scanned=" ).append( scanned );
-        sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' );
-        sb.append( ", index=" ).append( index );
-        sb.append( ", layout='" ).append( layout ).append( '\'' );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryGroup.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryGroup.java
deleted file mode 100644 (file)
index 1ca68a0..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-package org.apache.archiva.rest.api.model.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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-import org.apache.archiva.repository.Repository;
-import org.apache.archiva.repository.features.IndexCreationFeature;
-import org.apache.archiva.repository.features.RepositoryFeature;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@XmlRootElement(name="repositoryGroup")
-@Schema(name="RepositoryGroup", description = "Information about a repository group, which combines multiple repositories as one virtual repository.")
-public class RepositoryGroup implements Serializable
-{
-    private static final long serialVersionUID = -7319687481737616081L;
-    private String id;
-    private String name;
-    private List<String> repositories = new ArrayList<>(  );
-    private String location;
-    MergeConfiguration mergeConfiguration;
-
-    public RepositoryGroup( )
-    {
-    }
-
-    public RepositoryGroup(String id) {
-        this.id = id;
-    }
-
-    public static RepositoryGroup of( org.apache.archiva.repository.RepositoryGroup modelObj ) {
-        RepositoryGroup result = new RepositoryGroup( );
-        MergeConfiguration mergeConfig = new MergeConfiguration( );
-        result.setMergeConfiguration( mergeConfig );
-        result.setId( modelObj.getId() );
-        result.setName( modelObj.getName() );
-        result.setLocation( modelObj.getLocation().toString() );
-        result.setRepositories( modelObj.getRepositories().stream().map( Repository::getId ).collect( Collectors.toList()) );
-        if (modelObj.supportsFeature( IndexCreationFeature.class )) {
-            IndexCreationFeature icf = modelObj.getFeature( IndexCreationFeature.class ).get();
-            mergeConfig.setMergedIndexPath( icf.getIndexPath( ).toString() );
-            mergeConfig.setMergedIndexTtlMinutes( modelObj.getMergedIndexTTL( ) );
-            mergeConfig.setIndexMergeSchedule( modelObj.getSchedulingDefinition() );
-        }
-        return result;
-    }
-
-    @Schema(description = "The unique id of the repository group.")
-    public String getId( )
-    {
-        return id;
-    }
-
-    public void setId( String id )
-    {
-        this.id = id;
-    }
-
-    @Schema(description = "The list of ids of repositories which are member of the repository group.")
-    public List<String> getRepositories( )
-    {
-        return repositories;
-    }
-
-    public void setRepositories( List<String> repositories )
-    {
-        this.repositories = new ArrayList<>( repositories );
-    }
-
-    public void addRepository(String repositoryId) {
-        if (!this.repositories.contains( repositoryId )) {
-            this.repositories.add( repositoryId );
-        }
-    }
-
-    @Schema(name="merge_configuration",description = "The configuration for index merge.")
-    public MergeConfiguration getMergeConfiguration( )
-    {
-        return mergeConfiguration;
-    }
-
-    public void setMergeConfiguration( MergeConfiguration mergeConfiguration )
-    {
-        this.mergeConfiguration = mergeConfiguration;
-    }
-
-    @Schema(description = "The storage location of the repository. The merged index is stored relative to this location.")
-    public String getLocation( )
-    {
-        return location;
-    }
-
-    public void setLocation( String location )
-    {
-        this.location = location;
-    }
-
-    @Schema(description = "The name of the repository group")
-    public String getName( )
-    {
-        return name;
-    }
-
-    public void setName( String name )
-    {
-        this.name = name;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-
-        RepositoryGroup that = (RepositoryGroup) o;
-
-        return id.equals( that.id );
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        return id.hashCode( );
-    }
-
-    @Override
-    public String toString( )
-    {
-        final StringBuilder sb = new StringBuilder( "RepositoryGroup{" );
-        sb.append( "id='" ).append( id ).append( '\'' );
-        sb.append( ", name='" ).append( name ).append( '\'' );
-        sb.append( ", repositories=" ).append( repositories );
-        sb.append( ", location='" ).append( location ).append( '\'' );
-        sb.append( ", mergeConfiguration=" ).append( mergeConfiguration );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryStatistics.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryStatistics.java
deleted file mode 100644 (file)
index 1417a19..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-package org.apache.archiva.rest.api.model.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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-import org.apache.archiva.repository.scanner.RepositoryScanStatistics;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-import java.time.Duration;
-import java.time.OffsetDateTime;
-import java.time.ZoneOffset;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-@XmlRootElement(name="repositoryStatistics")
-@Schema(name="RepositoryStatistics", description = "Statistics data")
-public class RepositoryStatistics implements Serializable
-{
-    private static final long serialVersionUID = 7943367882738452531L;
-
-    private OffsetDateTime scanEndTime;
-    private OffsetDateTime scanStartTime;
-    private long scanDurationMs;
-    private long totalArtifactCount;
-    private long totalArtifactFileSize;
-    private long totalFileCount;
-    private long totalGroupCount;
-    private long totalProjectCount;
-    private long newFileCount;
-    private Map<String, Long> totalCountForType = new TreeMap<>(  );
-    private Map<String, Long> customValues = new TreeMap<>(  );
-
-    public RepositoryStatistics( )
-    {
-    }
-
-    public static RepositoryStatistics of( org.apache.archiva.metadata.repository.stats.model.RepositoryStatistics modelStats ) {
-        RepositoryStatistics newStats = new RepositoryStatistics( );
-        newStats.setScanStartTime( modelStats.getScanStartTime().toInstant().atOffset( ZoneOffset.UTC ) );
-        newStats.setScanEndTime( modelStats.getScanEndTime( ).toInstant( ).atOffset( ZoneOffset.UTC ) );
-        newStats.setNewFileCount( modelStats.getNewFileCount() );
-        newStats.setScanDurationMs( Duration.between( newStats.scanStartTime, newStats.scanEndTime ).toMillis() );
-        newStats.setTotalArtifactCount( modelStats.getTotalArtifactCount() );
-        newStats.setTotalArtifactFileSize( modelStats.getTotalArtifactFileSize() );
-        newStats.setTotalCountForType( modelStats.getTotalCountForType() );
-        newStats.setTotalFileCount( modelStats.getTotalFileCount() );
-        newStats.setTotalGroupCount( modelStats.getTotalGroupCount() );
-        newStats.setTotalProjectCount( modelStats.getTotalProjectCount() );
-        for (String key : modelStats.getAvailableCustomValues()) {
-            newStats.addCustomValue( key, modelStats.getCustomValue( key ) );
-        }
-        return newStats;
-    }
-
-    public static RepositoryStatistics of( RepositoryScanStatistics scanStatistics ) {
-        RepositoryStatistics newStats = new RepositoryStatistics( );
-        newStats.setScanStartTime( scanStatistics.getWhenGathered().toInstant().atOffset( ZoneOffset.UTC ) );
-        newStats.setScanEndTime( OffsetDateTime.now(ZoneOffset.UTC) );
-        newStats.setNewFileCount( scanStatistics.getNewFileCount() );
-        newStats.setScanDurationMs( Duration.between( newStats.scanStartTime, newStats.scanEndTime ).toMillis() );
-        newStats.setTotalArtifactCount( scanStatistics.getTotalFileCount() );
-        newStats.setTotalArtifactFileSize( scanStatistics.getTotalSize() );
-        newStats.setTotalFileCount( scanStatistics.getTotalFileCount() );
-        newStats.setTotalGroupCount( 0 );
-        newStats.setTotalProjectCount( 0 );
-        return newStats;
-    }
-
-    @Schema(name="scan_end_time", description = "Date and time when the last scan finished")
-    public OffsetDateTime getScanEndTime( )
-    {
-        return scanEndTime;
-    }
-
-    public void setScanEndTime( OffsetDateTime scanEndTime )
-    {
-        this.scanEndTime = scanEndTime;
-    }
-
-    @Schema( name = "scan_start_time", description = "Date and time when the last scan started" )
-    public OffsetDateTime getScanStartTime( )
-    {
-        return scanStartTime;
-    }
-
-    public void setScanStartTime( OffsetDateTime scanStartTime )
-    {
-        this.scanStartTime = scanStartTime;
-    }
-
-    @Schema(name="total_artifact_count", description = "The number of artifacts scanned")
-    public long getTotalArtifactCount( )
-    {
-        return totalArtifactCount;
-    }
-
-    public void setTotalArtifactCount( long totalArtifactCount )
-    {
-        this.totalArtifactCount = totalArtifactCount;
-    }
-
-    @Schema(name="total_artifact_file_size", description = "The cumulative size of all files scanned")
-    public long getTotalArtifactFileSize( )
-    {
-        return totalArtifactFileSize;
-    }
-
-    public void setTotalArtifactFileSize( long totalArtifactFileSize )
-    {
-        this.totalArtifactFileSize = totalArtifactFileSize;
-    }
-
-    @Schema(name="total_file_count", description = "The total number of files scanned")
-    public long getTotalFileCount( )
-    {
-        return totalFileCount;
-    }
-
-    public void setTotalFileCount( long totalFileCount )
-    {
-        this.totalFileCount = totalFileCount;
-    }
-
-    @Schema(name="total_group_count", description = "The number of groups scanned")
-    public long getTotalGroupCount( )
-    {
-        return totalGroupCount;
-    }
-
-    public void setTotalGroupCount( long totalGroupCount )
-    {
-        this.totalGroupCount = totalGroupCount;
-    }
-
-    @Schema(name="total_project_count", description = "The number of projects scanned")
-    public long getTotalProjectCount( )
-    {
-        return totalProjectCount;
-    }
-
-    public void setTotalProjectCount( long totalProjectCount )
-    {
-        this.totalProjectCount = totalProjectCount;
-    }
-
-    @Schema(name="new_file_count", description = "Number of files registered as new")
-    public long getNewFileCount( )
-    {
-        return newFileCount;
-    }
-
-    public void setNewFileCount( long newFileCount )
-    {
-        this.newFileCount = newFileCount;
-    }
-
-    @Schema(name="scan_duration_ms", description = "The duration of the last scan in ms")
-    public long getScanDurationMs( )
-    {
-        return scanDurationMs;
-    }
-
-    public void setScanDurationMs( long scanDurationMs )
-    {
-        this.scanDurationMs = scanDurationMs;
-    }
-
-    @Schema(name="total_count_for_type", description = "File counts partitioned by file types")
-    public Map<String, Long> getTotalCountForType( )
-    {
-        return totalCountForType;
-    }
-
-    public void setTotalCountForType( Map<String, Long> totalCountForType )
-    {
-        this.totalCountForType = new TreeMap<>( totalCountForType );
-    }
-
-    public void addTotalCountForType( String type, Long value )
-    {
-        this.totalCountForType.put( type, value );
-    }
-
-    @Schema(name="custom_values", description = "Custom statistic values")
-    public Map<String, Long> getCustomValues( )
-    {
-        return customValues;
-    }
-
-    public void setCustomValues( Map<String, Long> customValues )
-    {
-        this.customValues = new TreeMap<>(  customValues );
-    }
-
-    public void addCustomValue(String type, Long value) {
-        this.customValues.put( type, value );
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-
-        RepositoryStatistics that = (RepositoryStatistics) o;
-
-        if ( scanDurationMs != that.scanDurationMs ) return false;
-        if ( totalArtifactCount != that.totalArtifactCount ) return false;
-        if ( totalArtifactFileSize != that.totalArtifactFileSize ) return false;
-        if ( totalFileCount != that.totalFileCount ) return false;
-        if ( totalGroupCount != that.totalGroupCount ) return false;
-        if ( totalProjectCount != that.totalProjectCount ) return false;
-        if ( newFileCount != that.newFileCount ) return false;
-        if ( scanEndTime != null ? !scanEndTime.equals( that.scanEndTime ) : that.scanEndTime != null ) return false;
-        if ( scanStartTime != null ? !scanStartTime.equals( that.scanStartTime ) : that.scanStartTime != null )
-            return false;
-        if ( !totalCountForType.equals( that.totalCountForType ) ) return false;
-        return customValues.equals( that.customValues );
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        int result = scanEndTime != null ? scanEndTime.hashCode( ) : 0;
-        result = 31 * result + ( scanStartTime != null ? scanStartTime.hashCode( ) : 0 );
-        result = 31 * result + (int) ( scanDurationMs ^ ( scanDurationMs >>> 32 ) );
-        result = 31 * result + (int) ( totalArtifactCount ^ ( totalArtifactCount >>> 32 ) );
-        result = 31 * result + (int) ( totalArtifactFileSize ^ ( totalArtifactFileSize >>> 32 ) );
-        result = 31 * result + (int) ( totalFileCount ^ ( totalFileCount >>> 32 ) );
-        result = 31 * result + (int) ( totalGroupCount ^ ( totalGroupCount >>> 32 ) );
-        result = 31 * result + (int) ( totalProjectCount ^ ( totalProjectCount >>> 32 ) );
-        result = 31 * result + (int) ( newFileCount ^ ( newFileCount >>> 32 ) );
-        result = 31 * result + totalCountForType.hashCode( );
-        result = 31 * result + customValues.hashCode( );
-        return result;
-    }
-
-    @Override
-    public String toString( )
-    {
-        final StringBuilder sb = new StringBuilder( "RepositoryStatistics{" );
-        sb.append( "scanEndTime=" ).append( scanEndTime );
-        sb.append( ", scanStartTime=" ).append( scanStartTime );
-        sb.append( ", scanDurationMs=" ).append( scanDurationMs );
-        sb.append( ", totalArtifactCount=" ).append( totalArtifactCount );
-        sb.append( ", totalArtifactFileSize=" ).append( totalArtifactFileSize );
-        sb.append( ", totalFileCount=" ).append( totalFileCount );
-        sb.append( ", totalGroupCount=" ).append( totalGroupCount );
-        sb.append( ", totalProjectCount=" ).append( totalProjectCount );
-        sb.append( ", newFileCount=" ).append( newFileCount );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanStatus.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanStatus.java
deleted file mode 100644 (file)
index 27c6b02..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.apache.archiva.rest.api.model.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.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;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Schema(name="ScanStatus", description = "Status of repository scan tasks")
-public class ScanStatus implements Serializable
-{
-    private boolean scanRunning = false;
-    private int scanQueued = 0;
-    private boolean indexRunning = false;
-    private int indexQueued = 0;
-    private List<IndexingTask> indexingQueue = new ArrayList<>(  );
-    private List<ScanTask> scanQueue = new ArrayList<>(  );
-
-    public ScanStatus( )
-    {
-    }
-
-    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;
-
-    }
-
-    @Schema( name = "scan_running", description = "True, if a scan is currently running" )
-    public boolean isScanRunning( )
-    {
-        return scanRunning;
-    }
-
-    public void setScanRunning( boolean scanRunning )
-    {
-        this.scanRunning = scanRunning;
-    }
-
-    @Schema(name ="scan_queued", description = "Number of scans in the task queue")
-    public int getScanQueued( )
-    {
-        return scanQueued;
-    }
-
-    public void setScanQueued( int scanQueued )
-    {
-        this.scanQueued = scanQueued;
-    }
-
-    @Schema(name="index_running", description = "True, if there is a index task currently running")
-    public boolean isIndexRunning( )
-    {
-        return indexRunning;
-    }
-
-    public void setIndexRunning( boolean indexRunning )
-    {
-        this.indexRunning = indexRunning;
-    }
-
-    @Schema(name="index_queued", description = "Number of queued index tasks")
-    public int getIndexQueued( )
-    {
-        return indexQueued;
-    }
-
-    public void setIndexQueued( int indexQueued )
-    {
-        this.indexQueued = indexQueued;
-    }
-
-    @Schema( name = "indexing_queue", description = "List of indexing tasks waiting for execution" )
-    public List<IndexingTask> getIndexingQueue( )
-    {
-        return indexingQueue;
-    }
-
-    public void setIndexingQueue( List<IndexingTask> indexingQueue )
-    {
-        this.indexingQueue = new ArrayList<>( indexingQueue );
-    }
-
-    @Schema(name="scan_queue", description = "List of scan tasks waiting for execution")
-    public List<ScanTask> getScanQueue( )
-    {
-        return scanQueue;
-    }
-
-    public void setScanQueue( List<ScanTask> scanQueue )
-    {
-        this.scanQueue = new ArrayList<>( scanQueue );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanTask.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanTask.java
deleted file mode 100644 (file)
index 1dc1530..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.apache.archiva.rest.api.model.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.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;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Schema(name="ScanTask", description = "Repository scan task information")
-public class ScanTask implements Serializable
-{
-    private static final long serialVersionUID = -681163357370848098L;
-    private String repositoryId="";
-    private boolean updateRelatedArtifacts;
-    private boolean fullRepository;
-    private boolean running = false;
-    private String resource = "";
-    private long maxExecutionTimeMs = 0;
-
-    public static ScanTask of( MetadataScanTask repositoryTask ) {
-        ScanTask scanTask = new ScanTask( );
-        scanTask.setFullRepository( repositoryTask.isFullScan());
-        scanTask.setUpdateRelatedArtifacts( repositoryTask.isUpdateRelatedArtifacts() );
-        scanTask.setResource( repositoryTask.getResource() );
-        scanTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTimeMs() );
-        scanTask.setRepositoryId( repositoryTask.getRepositoryId( ) );
-        return scanTask;
-    }
-
-    @Schema(name="repository_id", description = "Identifier of the repository, this task is running on")
-    public String getRepositoryId( )
-    {
-        return repositoryId;
-    }
-
-    public void setRepositoryId( String repositoryId )
-    {
-        this.repositoryId = repositoryId==null?"":repositoryId;
-    }
-
-    @Schema(name="update_related_artifacts", description = "True, if related artifacts are updated too.")
-    public boolean isUpdateRelatedArtifacts( )
-    {
-        return updateRelatedArtifacts;
-    }
-
-    public void setUpdateRelatedArtifacts( boolean updateRelatedArtifacts )
-    {
-        this.updateRelatedArtifacts = updateRelatedArtifacts;
-    }
-
-    @Schema(name="full_repository",description = "True, if this is a full repository scan")
-    public boolean isFullRepository( )
-    {
-        return fullRepository;
-    }
-
-    public void setFullRepository( boolean fullRepository )
-    {
-        this.fullRepository = fullRepository;
-    }
-
-    @Schema(name="running", description = "True, if this task is currently running")
-    public boolean isRunning( )
-    {
-        return running;
-    }
-
-    public void setRunning( boolean running )
-    {
-        this.running = running;
-    }
-
-    @Schema(name="resource",description = "Name of the resource to update")
-    public String getResource( )
-    {
-        return resource;
-    }
-
-    public void setResource( String resource )
-    {
-        this.resource = resource==null?"":resource;
-    }
-
-    @Schema(name="max_excecution_time_ms",description = "Maximum execution time in ms")
-    public long getMaxExecutionTimeMs( )
-    {
-        return maxExecutionTimeMs;
-    }
-
-    public void setMaxExecutionTimeMs( long maxExecutionTimeMs )
-    {
-        this.maxExecutionTimeMs = maxExecutionTimeMs;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-
-        ScanTask scanTask = (ScanTask) o;
-
-        if ( updateRelatedArtifacts != scanTask.updateRelatedArtifacts ) return false;
-        if ( fullRepository != scanTask.fullRepository ) 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 + ( fullRepository ? 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( fullRepository );
-        sb.append( ", running=" ).append( running );
-        sb.append( ", resource='" ).append( resource ).append( '\'' );
-        sb.append( ", maxExecutionTimeMs=" ).append( maxExecutionTimeMs );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/SecurityConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/SecurityConfiguration.java
deleted file mode 100644 (file)
index efe02a4..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-package org.apache.archiva.rest.api.model.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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-import org.apache.archiva.admin.model.beans.RedbackRuntimeConfiguration;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@XmlRootElement(name = "securityConfiguration")
-@Schema(name = "SecurityConfiguration", description = "Security configuration attributes.")
-public class SecurityConfiguration implements Serializable
-{
-    private static final long serialVersionUID = -4186866365979053029L;
-
-    private List<String> activeUserManagers = new ArrayList<>(  );
-    private List<String> activeRbacManagers = new ArrayList<>(  );
-    private Map<String,String> properties = new TreeMap<>(  );
-    private boolean userCacheEnabled=false;
-    private boolean ldapActive=false;
-
-    public SecurityConfiguration() {
-
-    }
-
-    public static SecurityConfiguration ofRedbackConfiguration( RedbackRuntimeConfiguration configuration ) {
-        SecurityConfiguration secConfig = new SecurityConfiguration( );
-        secConfig.setActiveRbacManagers( configuration.getRbacManagerImpls() );
-        secConfig.setActiveUserManagers( configuration.getUserManagerImpls() );
-        secConfig.setProperties( configuration.getConfigurationProperties() );
-        boolean rbLdapActive = configuration.getUserManagerImpls( ).stream( ).anyMatch( um -> um.contains( "ldap" ) );
-        secConfig.setLdapActive( rbLdapActive );
-        secConfig.setUserCacheEnabled( configuration.isUseUsersCache() );
-        return secConfig;
-    }
-
-    @Schema(name="active_user_managers", description = "List of ids of the active user managers")
-    public List<String> getActiveUserManagers( )
-    {
-        return activeUserManagers;
-    }
-
-    public void setActiveUserManagers( List<String> activeUserManagers )
-    {
-        this.activeUserManagers = new ArrayList<>( activeUserManagers );
-    }
-
-    public void addSelectedUserManager(String userManager) {
-        this.activeUserManagers.add( userManager );
-    }
-
-    @Schema(name="active_rbac_managers", description = "List of ids of the active rbac managers")
-    public List<String> getActiveRbacManagers( )
-    {
-        return activeRbacManagers;
-    }
-
-    public void setActiveRbacManagers( List<String> activeRbacManagers )
-    {
-        this.activeRbacManagers = new ArrayList<>( activeRbacManagers );
-    }
-
-    public void addSelectedRbacManager(String rbacManager) {
-        this.activeRbacManagers.add( rbacManager );
-    }
-
-    @Schema(description = "Map of all security properties")
-    public Map<String, String> getProperties( )
-    {
-        return properties;
-    }
-
-    public void setProperties( Map<String, String> properties )
-    {
-        this.properties = new TreeMap<>( properties );
-    }
-
-    @Schema(name="user_cache_enabled", description = "True, if the user cache is active. It caches data from user backend.")
-    public boolean isUserCacheEnabled( )
-    {
-        return userCacheEnabled;
-    }
-
-    public void setUserCacheEnabled( boolean userCacheEnabled )
-    {
-        this.userCacheEnabled = userCacheEnabled;
-    }
-
-    @Schema(name="ldap_active", description = "True, if LDAP is used as user manager")
-    public boolean isLdapActive( )
-    {
-        return ldapActive;
-    }
-
-    public void setLdapActive( boolean ldapActive )
-    {
-        this.ldapActive = ldapActive;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o ) return true;
-        if ( o == null || getClass( ) != o.getClass( ) ) return false;
-
-        SecurityConfiguration that = (SecurityConfiguration) o;
-
-        if ( userCacheEnabled != that.userCacheEnabled ) return false;
-        if ( ldapActive != that.ldapActive ) return false;
-        if ( !activeUserManagers.equals( that.activeUserManagers ) ) return false;
-        if ( !activeRbacManagers.equals( that.activeRbacManagers ) ) return false;
-        return properties.equals( that.properties );
-    }
-
-    @Override
-    public int hashCode( )
-    {
-        int result = activeUserManagers.hashCode( );
-        result = 31 * result + activeRbacManagers.hashCode( );
-        result = 31 * result + properties.hashCode( );
-        result = 31 * result + ( userCacheEnabled ? 1 : 0 );
-        result = 31 * result + ( ldapActive ? 1 : 0 );
-        return result;
-    }
-
-    @SuppressWarnings( "StringBufferReplaceableByString" )
-    @Override
-    public String toString( )
-    {
-        final StringBuilder sb = new StringBuilder( "SecurityConfiguration{" );
-        sb.append( "active_user_managers=" ).append( activeUserManagers );
-        sb.append( ", active_rbac_managers=" ).append( activeRbacManagers );
-        sb.append( ", properties=" ).append( properties );
-        sb.append( ", user_cache_enabled=" ).append( userCacheEnabled );
-        sb.append( ", ldap_active=" ).append( ldapActive );
-        sb.append( '}' );
-        return sb.toString( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ValidationError.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ValidationError.java
deleted file mode 100644 (file)
index efa1ec9..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-package org.apache.archiva.rest.api.model.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.swagger.v3.oas.annotations.media.Schema;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@XmlRootElement(name = "validationError")
-@Schema(name = "ValidationError", description = "A validation error.")
-public class ValidationError implements Serializable
-{
-    private static final long serialVersionUID = 2079020598090660171L;
-
-    String key;
-    String field;
-    String category;
-    String type;
-    List<String> parameter;
-
-
-    public ValidationError( )
-    {
-    }
-
-    public ValidationError( String key, String field, String category, String type, List<String> parameter) {
-        this.key = key;
-        this.field = field;
-        this.category = category;
-        this.type = type;
-        if (parameter==null) {
-            this.parameter = new ArrayList<>( );
-        } else
-        {
-            this.parameter = parameter;
-        }
-    }
-
-    /**
-     * Creates a new instance based on the given error
-     * @param error the error instance
-     * @return
-     */
-    public static ValidationError of( org.apache.archiva.repository.validation.ValidationError error ) {
-        return error != null ? new ValidationError( error.getErrorKey( ), error.getAttribute( ), error.getCategory( ),
-            error.getType( ), error.getArguments( ).stream( ).map( Object::toString ).collect( Collectors.toList( ) ) )
-            : new ValidationError( );
-    }
-
-    /**
-     * Creates a new instance based on the field name and the error instance
-     * @param fieldName the name of the field to which the error applies
-     * @param error the error definition
-     * @return a new validation error instance
-     */
-    public static ValidationError of( String fieldName, org.apache.archiva.repository.validation.ValidationError error ) {
-        return error != null ? new ValidationError( error.getErrorKey( ), fieldName, error.getCategory( ),
-            error.getType( ), error.getArguments( ).stream( ).map( Object::toString ).collect( Collectors.toList( ) ) )
-            : new ValidationError( );
-    }
-
-    @Schema(name="key", description = "The full key of the validation error")
-    public String getKey( )
-    {
-        return key;
-    }
-
-    public void setKey( String key )
-    {
-        this.key = key;
-    }
-
-    @Schema(name="field", description = "The name of the field where the error was detected")
-    public String getField( )
-    {
-        return field;
-    }
-
-    public void setField( String field )
-    {
-        this.field = field;
-    }
-
-    @Schema(name="category", description = "The name of the category this error is assigned to")
-    public String getCategory( )
-    {
-        return category;
-    }
-
-    public void setCategory( String category )
-    {
-        this.category = category;
-    }
-
-    @Schema(name="type", description = "The type of the error. This is a unique string that defines the type of error, e.g. empty, bad_number_range, ... .")
-    public String getType( )
-    {
-        return type;
-    }
-
-    public void setType( String type )
-    {
-        this.type = type;
-    }
-
-    @Schema(name="parameter", description = "The list of parameters, that can be used to create a translated error message")
-    public List<String> getParameter( )
-    {
-        return parameter;
-    }
-
-    public void setParameter( List<String> parameter )
-    {
-        this.parameter = parameter;
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/ArtifactCleanupInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/ArtifactCleanupInfo.java
deleted file mode 100644 (file)
index 879bb8b..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.apache.archiva.rest.api.model.v2.repository;/*
- * 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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-
-import java.time.Period;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Schema(name="ArtifactCleanupInfo",description = "Information for artifact cleanup feature of repository")
-public class ArtifactCleanupInfo
-{
-    boolean deleteReleasedSnapshots;
-    Period retentionPeriod;
-    int retentionCount;
-
-    @Schema(name="delete_released_snapshots",description = "True, if snapshots are deleted after a release was published")
-    public boolean isDeleteReleasedSnapshots( )
-    {
-        return deleteReleasedSnapshots;
-    }
-
-    public void setDeleteReleasedSnapshots( boolean deleteReleasedSnapshots )
-    {
-        this.deleteReleasedSnapshots = deleteReleasedSnapshots;
-    }
-
-    @Schema(name="retention_period",description = "Time, after that snapshot artifacts are marked for deletion")
-    public Period getRetentionPeriod( )
-    {
-        return retentionPeriod;
-    }
-
-    public void setRetentionPeriod( Period retentionPeriod )
-    {
-        this.retentionPeriod = retentionPeriod;
-    }
-
-    @Schema(name="retention_count",description = "Maximum number of snapshot artifacts to keep")
-    public int getRetentionCount( )
-    {
-        return retentionCount;
-    }
-
-    public void setRetentionCount( int retentionCount )
-    {
-        this.retentionCount = retentionCount;
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/IndexCreationInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/IndexCreationInfo.java
deleted file mode 100644 (file)
index ebc506b..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.apache.archiva.rest.api.model.v2.repository;/*
- * 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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-import org.apache.archiva.repository.Repository;
-import org.apache.archiva.repository.storage.StorageAsset;
-
-import java.net.URI;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Schema(name="IndexCreationInfo",description = "Information about index creation feature of repositories")
-public class IndexCreationInfo
-{
-    private boolean skipPackedIndexCreation = false;
-    private String indexPath;
-    private String packedIndexPath;
-
-    @Schema(name="skip_packed_index_creation",description = "True, if the packed index will not be created")
-    public boolean isSkipPackedIndexCreation( )
-    {
-        return skipPackedIndexCreation;
-    }
-
-    public void setSkipPackedIndexCreation( boolean skipPackedIndexCreation )
-    {
-        this.skipPackedIndexCreation = skipPackedIndexCreation;
-    }
-
-    @Schema(name="index_path",description = "Path to the index directory relative to the repository base directory")
-    public String getIndexPath( )
-    {
-        return indexPath;
-    }
-
-    public void setIndexPath( String indexPath )
-    {
-        this.indexPath = indexPath;
-    }
-
-    @Schema(name="packed_index_path",description = "Path to the packed index directory relative to the repository base directory")
-    public String getPackedIndexPath( )
-    {
-        return packedIndexPath;
-    }
-
-    public void setPackedIndexPath( String packedIndexPath )
-    {
-        this.packedIndexPath = packedIndexPath;
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/RemoteIndexInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/RemoteIndexInfo.java
deleted file mode 100644 (file)
index c7dedc5..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.apache.archiva.rest.api.model.v2.repository;/*
- * 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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-
-import java.net.URI;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Schema(name="RemoteIndexInfo",description = "Information about remote indexes")
-public class RemoteIndexInfo
-{
-    private boolean downloadRemoteIndex = false;
-    private String indexUri;
-
-    @Schema(name="download_remote_index",description = "True, if the index will be downloaded from the remote repository")
-    public boolean isDownloadRemoteIndex( )
-    {
-        return downloadRemoteIndex;
-    }
-
-    public void setDownloadRemoteIndex( boolean downloadRemoteIndex )
-    {
-        this.downloadRemoteIndex = downloadRemoteIndex;
-    }
-
-    @Schema(name="index_uri", description = "The URI that specifies the path to the remote index")
-    public String getIndexUri( )
-    {
-        return indexUri;
-    }
-
-    public void setIndexUri( String indexUri )
-    {
-        this.indexUri = indexUri;
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/StagingInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/StagingInfo.java
deleted file mode 100644 (file)
index 1014d9f..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.apache.archiva.rest.api.model.v2.repository;/*
- * 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.
- */
-
-/*
- * 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.swagger.v3.oas.annotations.media.Schema;
-import org.apache.archiva.repository.ManagedRepository;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Schema(name="StagingInfo",description = "Information about staging feature of a repository")
-public class StagingInfo
-{
-    private String stagingRepository;
-    private boolean stageRepoNeeded;
-
-    @Schema(name="staging_repo",description = "The repository id of the staging repository")
-    public String getStagingRepository( )
-    {
-        return stagingRepository;
-    }
-
-    public void setStagingRepository( String stagingRepository )
-    {
-        this.stagingRepository = stagingRepository;
-    }
-
-    @Schema(name="stage_repo_needed",description = "True, if this repository needs a staging repository")
-    public boolean isStageRepoNeeded( )
-    {
-        return stageRepoNeeded;
-    }
-
-    public void setStageRepoNeeded( boolean stageRepoNeeded )
-    {
-        this.stageRepoNeeded = stageRepoNeeded;
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestError.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestError.java
deleted file mode 100644 (file)
index 17c5b89..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-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
- * 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.swagger.v3.oas.annotations.media.Schema;
-import org.apache.archiva.rest.api.model.v2.ValidationError;
-import org.apache.commons.lang3.StringUtils;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * @author Martin Stockhammer
- * @since 3.0
- */
-@XmlRootElement( name = "archivaRestError" )
-@Schema(name="ArchivaRestError", description = "Contains a list of error messages that resulted from the current REST call")
-public class ArchivaRestError
-    implements Serializable
-{
-
-    private static final long serialVersionUID = -8892617571273167067L;
-    private List<ErrorMessage> errorMessages = new ArrayList<>( 1 );
-    private List<ValidationError> validationErrors;
-
-    public ArchivaRestError()
-    {
-        // no op
-    }
-
-    public ArchivaRestError( ArchivaRestServiceException e )
-    {
-        errorMessages.addAll( e.getErrorMessages() );
-        if ( e.getErrorMessages().isEmpty() && StringUtils.isNotEmpty( e.getMessage() ) )
-        {
-            errorMessages.add( new ErrorMessage( e.getMessage(), null ) );
-        }
-        if (e instanceof ValidationException) {
-            this.validationErrors = ( (ValidationException) e ).getValidationErrors( );
-        }
-    }
-
-    public ArchivaRestError( ValidationException e )
-    {
-        errorMessages.addAll( e.getErrorMessages() );
-        if ( e.getErrorMessages().isEmpty() && StringUtils.isNotEmpty( e.getMessage() ) )
-        {
-            errorMessages.add( new ErrorMessage( e.getMessage(), null ) );
-        }
-        this.validationErrors = e.getValidationErrors( );
-    }
-
-    @Schema(name="error_messages", description = "The list of errors that occurred while processing the REST request")
-    public List<ErrorMessage> getErrorMessages()
-    {
-        return errorMessages;
-    }
-
-    public void setErrorMessages( List<ErrorMessage> errorMessages )
-    {
-        this.errorMessages = errorMessages;
-    }
-
-    public void addErrorMessage( ErrorMessage errorMessage )
-    {
-        this.errorMessages.add( errorMessage );
-    }
-
-    @Schema( name = "has_validation_errors", description = "True, if the error contains validation errors" )
-    public boolean hasValidationErrors( )
-    {
-        return this.validationErrors != null && this.validationErrors.size( ) > 0;
-    }
-
-    @Schema( name = "validation_errors", description = "The list of validation errors")
-    public List<ValidationError> getValidationErrors() {
-        return hasValidationErrors() ? this.validationErrors : Collections.emptyList( );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestServiceException.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestServiceException.java
deleted file mode 100644 (file)
index 3aabbe9..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-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
- * 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.util.ArrayList;
-import java.util.List;
-
-/**
- * Generic REST Service Exception that contains error information.
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-public class ArchivaRestServiceException extends Exception
-{
-    private int httpErrorCode = 500;
-
-    private List<ErrorMessage> errorMessages = new ArrayList<ErrorMessage>(0);
-
-    public ArchivaRestServiceException( String s )
-    {
-        super( s );
-    }
-
-    public ArchivaRestServiceException( String s, int httpErrorCode )
-    {
-        super( s );
-        this.httpErrorCode = httpErrorCode;
-    }
-
-    public ArchivaRestServiceException( ErrorMessage errorMessage )
-    {
-        errorMessages.add( errorMessage );
-    }
-
-    public ArchivaRestServiceException( ErrorMessage errorMessage, int httpResponseCode )
-    {
-        this.httpErrorCode = httpResponseCode;
-        errorMessages.add( errorMessage );
-    }
-
-    public ArchivaRestServiceException( List<ErrorMessage> errorMessage )
-    {
-        errorMessages.addAll( errorMessage );
-    }
-
-    public ArchivaRestServiceException( List<ErrorMessage> errorMessage, int httpResponseCode )
-    {
-        this.httpErrorCode = httpResponseCode;
-        errorMessages.addAll( errorMessage );
-    }
-
-    public int getHttpErrorCode()
-    {
-        return httpErrorCode;
-    }
-
-    public void setHttpErrorCode( int httpErrorCode )
-    {
-        this.httpErrorCode = httpErrorCode;
-    }
-
-    public List<ErrorMessage> getErrorMessages()
-    {
-        if ( errorMessages == null )
-        {
-            this.errorMessages = new ArrayList<ErrorMessage>();
-        }
-        return errorMessages;
-    }
-
-    public void setErrorMessages( List<ErrorMessage> errorMessages )
-    {
-        this.errorMessages = errorMessages;
-    }
-
-    public void addErrorMessage( ErrorMessage errorMessage )
-    {
-        this.errorMessages.add( errorMessage );
-    }
-
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java
deleted file mode 100644 (file)
index fee06c9..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-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
- * 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.
- */
-
-/*
- * 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.rest.api.services.v2.ErrorMessage;
-
-import java.util.List;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-public interface ErrorKeys
-{
-
-    String PREFIX = "archiva.";
-
-    String VALIDATION_ERROR = PREFIX + "validation_error";
-
-    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";
-    String LDAP_CF_INIT_FAILED = "archiva.ldap.cf.init.failed";
-    String LDAP_USER_MAPPER_INIT_FAILED = "archiva.ldap.usermapper.init.failed";
-    String LDAP_COMMUNICATION_ERROR = "archiva.ldap.communication_error";
-    String LDAP_INVALID_NAME = "archiva.ldap.invalid_name";
-    String LDAP_GENERIC_ERROR = "archiva.ldap.generic_error";
-    String LDAP_SERVICE_UNAVAILABLE = "archiva.ldap.service_unavailable";
-    String LDAP_SERVICE_AUTHENTICATION_FAILED = "archiva.ldap.authentication.failed";
-    String LDAP_SERVICE_AUTHENTICATION_NOT_SUPPORTED = "archiva.ldap.authentication.not_supported";
-    String LDAP_SERVICE_NO_PERMISSION = "archiva.ldap.no_permissions";
-
-    String PROPERTY_NOT_FOUND = "archiva.property.not.found";
-
-    String MISSING_DATA = "archiva.missing.data";
-
-    String REPOSITORY_GROUP_NOT_FOUND = REPOSITORY_GROUP_PREFIX+"notfound";
-    String REPOSITORY_GROUP_ADD_FAILED = REPOSITORY_GROUP_PREFIX+"add.failed"  ;
-    String REPOSITORY_GROUP_EXIST = REPOSITORY_GROUP_PREFIX+"exists";
-    String REPOSITORY_GROUP_UPDATE_FAILED = REPOSITORY_GROUP_PREFIX + "update.failed";
-
-    String REPOSITORY_GROUP_DELETE_FAILED = REPOSITORY_GROUP_PREFIX + "delete.failed";
-    String REPOSITORY_NOT_FOUND = REPOSITORY_PREFIX + "notfound";
-    String REPOSITORY_MANAGED_NOT_FOUND = REPOSITORY_PREFIX + "managed.notfound";
-    String REPOSITORY_REMOTE_NOT_FOUND = REPOSITORY_PREFIX + "remote.notfound";
-
-    String REPOSITORY_METADATA_ERROR = REPOSITORY_PREFIX + "metadata_error";
-
-    String TASK_QUEUE_FAILED = PREFIX + "task.queue_failed";
-    String REPOSITORY_SCAN_FAILED = REPOSITORY_PREFIX + "scan.failed";
-    String ARTIFACT_EXISTS_AT_DEST = REPOSITORY_PREFIX + "artifact.dest.exists";
-    String REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED = REPOSITORY_PREFIX + "remote.index.download_failed";
-    String REPOSITORY_WRONG_TYPE = REPOSITORY_PREFIX + "wrong_type";
-    String REPOSITORY_DELETE_FAILED = REPOSITORY_PREFIX + "delete.failed";
-    String REPOSITORY_INVALID_ID = REPOSITORY_PREFIX + "invalid.id";
-    String REPOSITORY_ID_EXISTS = REPOSITORY_PREFIX + "id.exists";
-    String REPOSITORY_UPDATE_FAILED = REPOSITORY_PREFIX + "update.failed";
-    String ARTIFACT_NOT_FOUND = REPOSITORY_PREFIX + "artifact.notfound";
-    String REPOSITORY_LAYOUT_ERROR = REPOSITORY_PREFIX + "layout.error";
-
-    String ARTIFACT_COPY_ERROR = REPOSITORY_PREFIX + "artifact.copy.error";
-
-    /**
-     * The given user was not found
-     * Parameters:
-     * - User Id
-     */
-    String USER_NOT_FOUND = PREFIX+"user.not_found";
-
-    /**
-     * Error from UserManager
-     * Parameters:
-     * - Error Message
-     */
-    String USER_MANAGER_ERROR = PREFIX+"user_manager.error";
-
-    /**
-     * Permission to the repository denied.
-     * Parameters:
-     * - Repository Id
-     * - Permission ID
-     */
-    String PERMISSION_REPOSITORY_DENIED = PREFIX + "permission.repository.denied";
-
-    /**
-     * A generic authorization error thrown during the authorization check.
-     * Parameters:
-     * - Error message
-     */
-    String AUTHORIZATION_ERROR = PREFIX + "authorization.error";
-
-    /**
-     * When the operation needs authentication, but not authenticated user was found in the request context.
-     */
-    String NOT_AUTHENTICATED = PREFIX + "user.not_authenticated";
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorMessage.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorMessage.java
deleted file mode 100644 (file)
index c8f767c..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-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
- * 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.swagger.v3.oas.annotations.media.Schema;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-
-/**
- * @author Olivier Lamy
- * @author Martin Stockhammer
- * @since 3.0
- */
-@XmlRootElement( name = "errorMessage" )
-@Schema(name="ErrorMessage",description = "Information about the error, that occurred while processing the REST request.")
-public class ErrorMessage
-    implements Serializable
-{
-    private String errorKey = "";
-
-    private String[] args = EMPTY;
-
-    private String message = "";
-
-    private static final String[] EMPTY = new String[0];
-
-    public ErrorMessage()
-    {
-        // no op
-    }
-
-    public ErrorMessage( String errorKey )
-    {
-        this.errorKey = errorKey;
-        this.args = EMPTY;
-    }
-
-    public ErrorMessage( String errorKey, String[] args )
-    {
-        this.errorKey = errorKey;
-        this.args = args;
-    }
-
-    public static ErrorMessage of(String errorKey, String... args) {
-        return new ErrorMessage( errorKey, args );
-    }
-
-    @Schema(name="error_key", description = "The key of the error message. If this is empty, the message message must be set.")
-    public String getErrorKey()
-    {
-        return errorKey;
-    }
-
-    public void setErrorKey( String errorKey )
-    {
-        this.errorKey = errorKey;
-    }
-
-    @Schema(description = "Parameters that can be filled to the translated error message")
-    public String[] getArgs()
-    {
-        return args;
-    }
-
-    public void setArgs( String[] args )
-    {
-        this.args = args;
-    }
-
-    @Schema(description = "Full error message. Either additional to the key in the default language, or if the message is without key.")
-    public String getMessage()
-    {
-        return message;
-    }
-
-    public void setMessage( String message )
-    {
-        this.message = message;
-    }
-
-    public ErrorMessage message( String message )
-    {
-        this.message = message;
-        return this;
-    }
-}
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
deleted file mode 100644 (file)
index 3da6743..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-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
- * 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.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.headers.Header;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.parameters.RequestBody;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import org.apache.archiva.components.rest.model.PagedResult;
-import org.apache.archiva.redback.authorization.RedbackAuthorization;
-import org.apache.archiva.rest.api.model.v2.RepositoryGroup;
-import org.apache.archiva.security.common.ArchivaRoleConstants;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Response;
-import java.util.List;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static org.apache.archiva.rest.api.services.v2.RestConfiguration.DEFAULT_PAGE_LIMIT;
-
-/**
- * Endpoint for repository groups that combine multiple repositories into a single virtual repository.
- *
- * @author Olivier Lamy
- * @author Martin Stockhammer
- * @since 3.0
- */
-@Path( "/repository_groups" )
-@Schema( name = "RepositoryGroups", description = "Managing of repository groups or virtual repositories" )
-public interface RepositoryGroupService
-{
-    @Path( "" )
-    @GET
-    @Produces( {APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Returns all repository group entries.",
-        parameters = {
-            @Parameter( name = "q", description = "Search term" ),
-            @Parameter( name = "offset", description = "The offset of the first element returned" ),
-            @Parameter( name = "limit", description = "Maximum number of items to return in the response" ),
-            @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ),
-            @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" )
-        },
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the list could be returned",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    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( "id" ) List<String> orderBy,
-                                                        @QueryParam( "order" ) @DefaultValue( "asc" ) String order )
-        throws ArchivaRestServiceException;
-
-    @Path( "{id}" )
-    @GET
-    @Produces( {APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Returns a single repository group configuration.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the configuration is returned",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The repository group with the given id does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    RepositoryGroup getRepositoryGroup( @PathParam( "id" ) String repositoryGroupId )
-        throws ArchivaRestServiceException;
-
-    @Path( "" )
-    @POST
-    @Consumes( {APPLICATION_JSON} )
-    @Produces( {APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Creates a new group entry.",
-        requestBody =
-        @RequestBody( required = true, description = "The configuration of the repository group.",
-            content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) )
-        )
-        ,
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "201",
-                description = "If the repository group was created",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) )
-            ),
-            @ApiResponse( responseCode = "303", description = "The repository group exists already",
-                headers = {
-                    @Header( name = "Location", description = "The URL of existing group", schema = @Schema( type = "string" ) )
-                }
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "422", description = "The body data is not valid",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    RepositoryGroup addRepositoryGroup( RepositoryGroup repositoryGroup )
-        throws ArchivaRestServiceException;
-
-    @Path( "{id}" )
-    @PUT
-    @Consumes( {APPLICATION_JSON} )
-    @Produces( {APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Returns all repository group entries.",
-        requestBody =
-        @RequestBody( required = true, description = "The configuration of the repository group.",
-            content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) )
-        )
-        ,
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the group is returned",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The group with the given id does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "422", description = "The body data is not valid",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    RepositoryGroup updateRepositoryGroup( @PathParam( "id" ) String groupId, RepositoryGroup repositoryGroup )
-        throws ArchivaRestServiceException;
-
-    @Path( "{id}" )
-    @DELETE
-    @Produces( {APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Deletes the repository group entry with the given id.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the group was deleted"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The group with the given id does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-        }
-    )
-    Response deleteRepositoryGroup( @PathParam( "id" ) String repositoryGroupId )
-        throws ArchivaRestServiceException;
-
-    @Path( "{id}/repositories/{repositoryId}" )
-    @PUT
-    @Produces( {APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Adds the repository with the given id to the repository group.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the repository was added or if it was already part of the group"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The group with the given id does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-        }
-    )
-    RepositoryGroup addRepositoryToGroup( @PathParam( "id" ) String repositoryGroupId,
-                                          @PathParam( "repositoryId" ) String repositoryId )
-        throws ArchivaRestServiceException;
-
-    @Path( "{id}/repositories/{repositoryId}" )
-    @DELETE
-    @Produces( {APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Removes the repository with the given id from the repository group.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the repository was removed."
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "Either the group with the given id does not exist, or the repository was not part of the group.",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-        }
-    )
-    RepositoryGroup deleteRepositoryFromGroup( @PathParam( "id" ) String repositoryGroupId,
-                                               @PathParam( "repositoryId" ) String repositoryId )
-        throws ArchivaRestServiceException;
-
-
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java
deleted file mode 100644 (file)
index c9c6f41..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-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
- * 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.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.apache.archiva.components.rest.model.PagedResult;
-import org.apache.archiva.redback.authorization.RedbackAuthorization;
-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.security.common.ArchivaRoleConstants;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import java.util.List;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static org.apache.archiva.rest.api.services.v2.RestConfiguration.DEFAULT_PAGE_LIMIT;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-@Path( "repositories" )
-@Tag(name = "v2")
-@Tag(name = "v2/Repositories")
-@Schema(name="RepositoryService",description = "Manage repositories of all types")
-public interface RepositoryService
-{
-
-    @Path( "" )
-    @GET
-    @Produces( {APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Returns all managed repositories.",
-        parameters = {
-            @Parameter( name = "q", description = "Search term" ),
-            @Parameter( name = "offset", description = "The offset of the first element returned" ),
-            @Parameter( name = "limit", description = "Maximum number of items to return in the response" ),
-            @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ),
-            @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" ),
-            @Parameter( name = "locale", description = "The locale for name and description" )
-        },
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the list could be returned",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    PagedResult<Repository> getRepositories( @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm,
-                                             @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset,
-                                             @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit,
-                                             @QueryParam( "orderBy" ) @DefaultValue( "id" ) List<String> orderBy,
-                                             @QueryParam( "order" ) @DefaultValue( "asc" ) String order,
-                                             @QueryParam( "locale" ) String localeString) throws ArchivaRestServiceException;
-
-    @Path( "managed/{id}/statistics" )
-    @GET
-    @Produces( {APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Returns repository statistic data.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the statistics could be returned",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryStatistics.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The repository does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    RepositoryStatistics getManagedRepositoryStatistics( @PathParam( "id" ) String repositoryId )
-        throws ArchivaRestServiceException;
-
-    @Path ("managed/{id}/scan/schedule")
-    @POST
-    @Produces ({ APPLICATION_JSON })
-    @Consumes({ APPLICATION_JSON })
-    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
-    @Operation( summary = "Returns repository statistic data.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the statistics could be returned"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The repository does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    Response scheduleRepositoryScan( @PathParam ("id") String repositoryId,
-                                     @QueryParam ("fullScan") boolean fullScan )
-        throws ArchivaRestServiceException;
-
-
-    @Path ("managed/{id}/scan/now")
-    @POST
-    @Produces ({ APPLICATION_JSON })
-    @Consumes({ APPLICATION_JSON })
-    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
-    @Operation( summary = "Runs a repository scan instantly and waits for the response.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the statistics could be returned",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryStatistics.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The repository does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    RepositoryStatistics scanRepositoryImmediately( @PathParam ("id") String repositoryId )
-        throws ArchivaRestServiceException;
-
-
-    @Path ("managed/{id}/scan/status")
-    @GET
-    @Produces ({ APPLICATION_JSON })
-    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
-    @Operation( summary = "Returns status of running and scheduled scans.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the status could be returned",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ScanStatus.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The repository does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    ScanStatus getScanStatus( @PathParam ("id") String repositoryId )
-        throws ArchivaRestServiceException;
-
-    @Path ("managed/{id}/scan")
-    @DELETE
-    @Produces ({ APPLICATION_JSON })
-    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
-    @Operation( summary = "Cancels and removes all tasks for the given repository.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the task was removed successfully"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The repository does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    Response removeScanningTaskFromQueue( @PathParam ("id") String repositoryId )
-        throws ArchivaRestServiceException;
-
-
-
-    @Path ("remote/{id}/index/download/start")
-    @POST
-    @Produces ({ APPLICATION_JSON })
-    @Consumes({ APPLICATION_JSON })
-    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
-    @Operation( summary = "Schedules a task for remote index download.",
-        parameters = {
-            @Parameter( name = "full", description = "If true, download the full index, otherwise try a update download." )
-        },
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the task was scheduled"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The repository does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    Response scheduleDownloadRemoteIndex( @PathParam ("id") String repositoryId,
-                                              @QueryParam( "immediate" ) boolean immediately,
-                                              @QueryParam ("full") boolean full, @Context UriInfo uriInfo )
-        throws ArchivaRestServiceException;
-
-
-    @Path ("remote/index/downloads")
-    @GET
-    @Produces ({ APPLICATION_JSON })
-    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
-    @Operation( summary = "Returns a list of running downloads from the remote repository.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the artifact was deleted"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    List<String> getRunningRemoteDownloads();
-
-
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RestConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RestConfiguration.java
deleted file mode 100644 (file)
index 10118d0..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-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
- * 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.
- */
-
-/*
- * 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.
- */
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-public interface RestConfiguration
-{
-    String DEFAULT_PAGE_LIMIT = "10";
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/SecurityConfigurationService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/SecurityConfigurationService.java
deleted file mode 100644 (file)
index e8cc0d9..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-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
- * 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.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.enums.ParameterIn;
-import io.swagger.v3.oas.annotations.media.ArraySchema;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.apache.archiva.components.rest.model.PagedResult;
-import org.apache.archiva.components.rest.model.PropertyEntry;
-import org.apache.archiva.redback.authorization.RedbackAuthorization;
-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.SecurityConfiguration;
-import org.apache.archiva.security.common.ArchivaRoleConstants;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Response;
-import java.util.List;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static org.apache.archiva.rest.api.services.v2.RestConfiguration.DEFAULT_PAGE_LIMIT;
-
-/**
- *
- * Service for configuration of redback and security related settings.
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-@Path( "/security" )
-@Tag(name = "v2")
-@Tag(name = "v2/Security")
-@SecurityRequirement(name = "BearerAuth")
-public interface SecurityConfigurationService
-{
-    @Path("config")
-    @GET
-    @Produces({ APPLICATION_JSON })
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Returns the security configuration that is currently active.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the configuration could be retrieved",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = SecurityConfiguration.class))
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    SecurityConfiguration getConfiguration()
-        throws ArchivaRestServiceException;
-
-    @Path("config")
-    @PUT
-    @Consumes({ APPLICATION_JSON })
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Updates the security configuration.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the configuration was updated"
-            ),
-            @ApiResponse( responseCode = "422", description = "Invalid content data",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the configuration",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    SecurityConfiguration updateConfiguration( SecurityConfiguration newConfiguration)
-        throws ArchivaRestServiceException;
-
-
-    @Path( "config/properties" )
-    @GET
-    @Produces( { APPLICATION_JSON } )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Returns all configuration properties. The result is paged.",
-        parameters = {
-            @Parameter(name = "q", description = "Search term"),
-            @Parameter(name = "offset", description = "The offset of the first element returned"),
-            @Parameter(name = "limit", description = "Maximum number of items to return in the response"),
-            @Parameter(name = "orderBy", description = "List of attribute used for sorting (key, value)"),
-            @Parameter(name = "order", description = "The sort order. Either ascending (asc) or descending (desc)")
-        },
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the list could be returned",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PagedResult.class))
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    PagedResult<PropertyEntry> getConfigurationProperties( @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("order") @DefaultValue( "asc" ) String order ) throws ArchivaRestServiceException;
-
-    @Path("config/properties/{propertyName}")
-    @GET
-    @Produces({ APPLICATION_JSON })
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Returns a single configuration property value.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        parameters = {
-            @Parameter(in = ParameterIn.PATH, name="propertyName", description = "The name of the property to get the value for")
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the configuration could be retrieved",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PropertyEntry.class))
-            ),
-            @ApiResponse( responseCode = "404", description = "The given property name does not exist",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    PropertyEntry getConfigurationProperty( @PathParam ( "propertyName" )  String propertyName)
-        throws ArchivaRestServiceException;
-
-
-    @Path("config/properties/{propertyName}")
-    @PUT
-    @Consumes({ APPLICATION_JSON})
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Updates a single property value of the security configuration.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        parameters = {
-            @Parameter(in = ParameterIn.PATH, name="propertyName", description = "The name of the property to update")
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the property value was updated."
-            ),
-            @ApiResponse( responseCode = "400", description = "The body data is not valid",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ),
-            @ApiResponse( responseCode = "404", description = "The given property name does not exist",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    Response updateConfigurationProperty( @PathParam ( "propertyName" )  String propertyName, PropertyEntry propertyValue)
-        throws ArchivaRestServiceException;
-
-    @Path("config/ldap")
-    @GET
-    @Produces({ APPLICATION_JSON })
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Returns the LDAP configuration that is currently active.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the configuration could be retrieved",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = LdapConfiguration.class))
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    LdapConfiguration getLdapConfiguration( ) throws ArchivaRestServiceException;
-
-    @Path("config/ldap")
-    @PUT
-    @Consumes({ APPLICATION_JSON })
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Updates the LDAP configuration that is currently active.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the configuration was updated"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    LdapConfiguration updateLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException;
-
-    @Path("config/ldap/verify")
-    @POST
-    @Consumes({ APPLICATION_JSON })
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Checks the given LDAP configuration.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the check was successful"
-            ),
-            @ApiResponse( responseCode = "400",
-                description = "If the check was not successful",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class ))
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    Response verifyLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException;
-
-    @Path("config/cache")
-    @GET
-    @Produces({ APPLICATION_JSON })
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Returns the cache configuration that is currently active.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the configuration could be retrieved",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = CacheConfiguration.class))
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    CacheConfiguration getCacheConfiguration( ) throws ArchivaRestServiceException;
-
-    @Path("config/cache")
-    @PUT
-    @Consumes({ APPLICATION_JSON })
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Updates the LDAP configuration that is currently active.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the configuration was updated"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    CacheConfiguration updateCacheConfiguration( CacheConfiguration cacheConfiguration ) throws ArchivaRestServiceException;
-
-
-    @Path("user_managers")
-    @GET
-    @Produces({ APPLICATION_JSON })
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Returns the available user manager implementations.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the list could be retrieved",
-                content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema(
-                    schema = @Schema(implementation = BeanInformation.class)))
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    List<BeanInformation> getAvailableUserManagers()
-        throws ArchivaRestServiceException;
-
-    @Path("rbac_managers")
-    @GET
-    @Produces({ APPLICATION_JSON })
-    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
-    @Operation( summary = "Returns the available RBAC manager implementations.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the list could be retrieved",
-                content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema(
-                    schema = @Schema(implementation = BeanInformation.class)))
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
-        }
-    )
-    List<BeanInformation> getAvailableRbacManagers()
-        throws ArchivaRestServiceException;
-
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ValidationException.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ValidationException.java
deleted file mode 100644 (file)
index 7c44f29..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-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
- * 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.repository.Repository;
-import org.apache.archiva.repository.validation.ValidationResponse;
-import org.apache.archiva.rest.api.model.v2.ValidationError;
-
-import java.util.ArrayList;
-import java.util.Collections;
-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
-{
-    public static final int DEFAULT_CODE = 422;
-
-    public static final ErrorMessage DEFAULT_MESSAGE = new ErrorMessage( ErrorKeys.VALIDATION_ERROR );
-
-    private List<ValidationError> validationErrors;
-
-    public ValidationException( )
-    {
-        super( DEFAULT_MESSAGE, DEFAULT_CODE );
-    }
-
-    public ValidationException( int errorCode )
-    {
-        super( DEFAULT_MESSAGE, errorCode );
-    }
-
-    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 )
-    {
-        return new ValidationException( errorList.stream( ).map( ValidationError::of ).collect( Collectors.toList( ) ) );
-    }
-
-    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
-        {
-            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;
-    }
-
-    public void setValidationErrors( List<ValidationError> validationErrors )
-    {
-        this.validationErrors = validationErrors;
-    }
-
-    public void addValidationError( ValidationError error )
-    {
-        if ( this.validationErrors == null )
-        {
-            this.validationErrors = new ArrayList<>( );
-        }
-        this.validationErrors.add( error );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/maven/MavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/maven/MavenManagedRepositoryService.java
deleted file mode 100644 (file)
index 5e63682..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-package org.apache.archiva.rest.api.services.v2.maven;
-/*
- * 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.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.headers.Header;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.security.OAuthScope;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.apache.archiva.components.rest.model.PagedResult;
-import org.apache.archiva.redback.authorization.RedbackAuthorization;
-import org.apache.archiva.rest.api.model.v2.FileInfo;
-import org.apache.archiva.rest.api.model.v2.MavenManagedRepository;
-import org.apache.archiva.rest.api.model.v2.MavenManagedRepositoryUpdate;
-import org.apache.archiva.rest.api.services.v2.ArchivaRestError;
-import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
-import org.apache.archiva.security.common.ArchivaRoleConstants;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.util.List;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static org.apache.archiva.rest.api.services.v2.RestConfiguration.DEFAULT_PAGE_LIMIT;
-
-/**
- * Service interface for managing managed maven repositories
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-@Schema( name = "ManagedRepositoryService", description = "Managing and configuration of managed repositories" )
-@Path( "repositories/maven/managed" )
-@Tag(name = "v2")
-@Tag(name = "v2/Repositories")
-public interface MavenManagedRepositoryService
-{
-    @Path( "" )
-    @GET
-    @Produces( {APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Returns all managed repositories.",
-        parameters = {
-            @Parameter( name = "q", description = "Search term" ),
-            @Parameter( name = "offset", description = "The offset of the first element returned" ),
-            @Parameter( name = "limit", description = "Maximum number of items to return in the response" ),
-            @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ),
-            @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" )
-        },
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the list could be returned",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    PagedResult<MavenManagedRepository> getManagedRepositories(
-        @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm,
-        @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset,
-        @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit,
-        @QueryParam( "orderBy" ) @DefaultValue( "id" ) List<String> orderBy,
-        @QueryParam( "order" ) @DefaultValue( "asc" ) String order )
-        throws ArchivaRestServiceException;
-
-
-    @Path( "{id}" )
-    @GET
-    @Produces( {MediaType.APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Returns the managed repository with the given id.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the managed repository could be returned",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    MavenManagedRepository getManagedRepository( @PathParam( "id" ) String repositoryId )
-        throws ArchivaRestServiceException;
-
-
-    @Path( "{id}" )
-    @DELETE
-    @Produces( {MediaType.APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Deletes the managed repository with the given id.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the managed repository could be returned"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    Response deleteManagedRepository( @PathParam( "id" ) String repositoryId,
-                                      @QueryParam( "deleteContent" ) boolean deleteContent )
-        throws ArchivaRestServiceException;
-
-
-    @Path( "" )
-    @POST
-    @Consumes( {MediaType.APPLICATION_JSON} )
-    @Produces( {MediaType.APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Creates the managed repository",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "201",
-                description = "If the managed repository could be created",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) )
-            ),
-            @ApiResponse( responseCode = "303", description = "The repository exists already",
-                headers = {
-                    @Header( name = "Location", description = "The URL of existing repository ", schema = @Schema( type = "string" ) )
-                }
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "422", description = "The body data is not valid",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    MavenManagedRepository addManagedRepository( MavenManagedRepository managedRepository )
-        throws ArchivaRestServiceException;
-
-
-    @Path( "{id}" )
-    @PUT
-    @Consumes( {MediaType.APPLICATION_JSON} )
-    @Produces( {MediaType.APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
-    @Operation( summary = "Updates the managed repository with the given id",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the managed repository could be updated",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "422", description = "The body data is not valid",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    MavenManagedRepository updateManagedRepository( @PathParam( "id" ) String repositoryId,  MavenManagedRepositoryUpdate managedRepository )
-        throws ArchivaRestServiceException;
-
-
-    @Path( "{id}/path/{filePath: .+}" )
-    @GET
-    @Produces( {MediaType.APPLICATION_JSON} )
-    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, resource = "{id}")
-    @Operation( summary = "Returns the status of a given file in the repository",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the file status is returned",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = FileInfo.class ) )
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the file does not exist.",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    FileInfo getFileStatus( @PathParam( "id" ) String repositoryId, @PathParam( "filePath" ) String fileLocation )
-        throws ArchivaRestServiceException;
-
-
-    /**
-     * Permissions are checked in impl
-     * will copy an artifact from the source repository to the target repository
-     */
-    @Path ("{srcId}/path/{path: .+}/copyto/{dstId}")
-    @POST
-    @Produces({APPLICATION_JSON})
-    @RedbackAuthorization (noPermission = true)
-    @Operation( summary = "Copies a artifact from the source repository to the destination repository",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS,
-                scopes = {
-                    "{srcId}"
-                }
-            ),
-            @SecurityRequirement(
-                name= ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD,
-                scopes = {
-                    "{dstId}"
-                }
-            )
-
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the artifact was copied"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The repository does not exist, or if the artifact was not found",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    Response copyArtifact( @PathParam( "srcId" ) String srcRepositoryId, @PathParam( "dstId" ) String dstRepositoryId,
-                           @PathParam( "path" ) String path )
-        throws ArchivaRestServiceException;
-
-
-    @Path ("{id}/path/{path: .+}")
-    @DELETE
-    @Consumes ({ APPLICATION_JSON })
-    @RedbackAuthorization (noPermission = true)
-    @Operation( summary = "Deletes a artifact in the repository.",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the artifact was deleted"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The repository or the artifact does not exist",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    Response deleteArtifact( @PathParam( "id" ) String repositoryId, @PathParam( "path" ) String path )
-        throws ArchivaRestServiceException;
-
-    @Path ( "{id}/co/{group}/{project}/{version}" )
-    @DELETE
-    @Produces ({ MediaType.APPLICATION_JSON })
-    @RedbackAuthorization (noPermission = true)
-    @Operation( summary = "Removes a version tree in the repository",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the deletion was successful"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete in repositories",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the version does not exist.",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    Response removeProjectVersion( @PathParam ( "id" ) String repositoryId,
-                                   @PathParam ( "group" ) String namespace, @PathParam ( "project" ) String projectId,
-                                   @PathParam ( "version" ) String version )
-        throws org.apache.archiva.rest.api.services.ArchivaRestServiceException;
-
-
-    @Path ( "{id}/co/{group}/{project}" )
-    @DELETE
-    @Produces ({ MediaType.APPLICATION_JSON })
-    @RedbackAuthorization (noPermission = true)
-    @Operation( summary = "Removes a project tree in the repository",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the deletion was successful"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete in repositories",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the project does not exist.",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    Response deleteProject( @PathParam ("id") String repositoryId, @PathParam ( "group" ) String namespace, @PathParam ( "project" ) String projectId )
-        throws org.apache.archiva.rest.api.services.ArchivaRestServiceException;
-
-    @Path ( "{id}/co/{namespace}" )
-    @DELETE
-    @Produces ({ MediaType.APPLICATION_JSON })
-    @RedbackAuthorization (noPermission = true)
-    @Operation( summary = "Removes a namespace tree in the repository",
-        security = {
-            @SecurityRequirement(
-                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
-            )
-        },
-        responses = {
-            @ApiResponse( responseCode = "200",
-                description = "If the deletion was successful"
-            ),
-            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete namespaces in repositories",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
-            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the namespace does not exist.",
-                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
-        }
-    )
-    Response deleteNamespace( @PathParam ("id") String repositoryId, @PathParam ( "namespace" ) String namespace )
-        throws org.apache.archiva.rest.api.services.ArchivaRestServiceException;
-
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/package-info.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/package-info.java
deleted file mode 100644 (file)
index 0cd02b0..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * <p>This is the V2 REST API of Archiva. It uses JAX-RS annotations for defining the endpoints.
- * The API is documented with OpenApi annotations.</p>
- *
- * <h3>Some design principles of the API and classes:</h3>
- * <ul>
- *     <li>All services use V2 model classes. Internal models are always converted to V2 classes.</li>
- *     <li>Schema attributes use the snake case syntax (lower case with '_' as divider)</li>
- *     <li>Return code <code>200</code> and <code>201</code> (POST) is used for successful execution.</li>
- *     <li>Return code <code>403</code> is used, if the user has not the permission for the action.</li>
- *     <li>Return code <code>422</code> is used for input that has invalid data.</li>
- * </ul>
- *
- * <h4>Querying entity lists</h4>
- * <p>The main entities of a given path are retrieved on the base path.
- * Further sub entities or entries may be retrieved via subpaths.
- * A single entity is returned by the "{id}" path. Be careful with technical paths that are parallel to the
- * id path. Avoid naming conflicts with the id and technical paths.
- * Entity attributes may be retrieved by "{id}/{attribute}" path or if there are lists or collections by
- * "{id}/mycollection/{subentryid}"</p>
- *
- * <ul>
- *  <li><code>GET</code> method is used for retrieving entities on the base path ""</li>
- *  <li>The query for base entities should always return a paged result and be filterable and sortable</li>
- *  <li>Query parameters for filtering, ordering and limits should be optional and proper defaults must be set</li>
- *  <li>Return code <code>200</code> is used for successful retrieval</li>
- *  <li>This action is idempotent</li>
- * </ul>
- *
- * <h4>Querying single entities</h4>
- * <p>Single entities are retrieved on the path "{id}"</p>
- * <ul>
- *  <li><code>GET</code> method is used for retrieving a single entity. The id is always a path parameter.</li>
- *  <li>Return code <code>200</code> is used for successful retrieval</li>
- *  <li>Return code <code>404</code> is used if the entity with the given id does not exist</li>
- *  <li>This action is idempotent</li>
- * </ul>
- *
- * <h4>Creating entities</h4>
- * <p>The main entities are created on the base path "".</p>
- * <ul>
- *     <li><code>POST</code> is used for creating new entities</li>
- *     <li>The <code>POST</code> body must always have a complete definition of the entity.</li>
- *     <li>A unique <code>id</code> or <code>name</code> attribute is required for entities. If the id is generated during POST,
- *     it must be returned by response body.</li>
- *     <li>A successful <code>POST</code> request should always return the entity definition as it would be returned by the GET request.</li>
- *     <li>Return code <code>201</code> is used for successful creation of the new entity.</li>
- *     <li>A successful response has a <code>Location</code> header with the URL for retrieving the single created entity.</li>
- *     <li>Return code <code>303</code> is used, if the entity exists already</li>
- *     <li>This action is not idempotent</li>
- * </ul>
- *
- * <h4>Updating entities</h4>
- * <p>The path for entity update must contain the '{id}' of the entity. The path should be the same as for the GET operation.</p>
- * <ul>
- *     <li><code>PUT</code> is used for updating existing entities</li>
- *     <li>The body contains a JSON object. Only existing attributes are updated.</li>
- *     <li>A successful PUT request should return the complete entity definition as it would be returned by the GET request.</li>
- *     <li>Return code <code>200</code> is used for successful update of the new entity. Even if nothing changed.</li>
- *     <li>This action is idempotent</li>
- * </ul>
- *
- * <h4>Deleting entities</h4>
- * <p>The path for entity deletion must contain the '{id}' of the entity. The path should be the same as
- * for the GET operation.</p>
- * <ul>
- *     <li><code>DELETE</code> is used for deleting existing entities</li>
- *     <li>The successful operation has no request and no response body</li>
- *     <li>Return code <code>200</code> is used for successful deletion of the new entity.</li>
- *     <li>This action is not idempotent</li>
- * </ul>
- *
- * <h4>Errors</h4>
- * <ul>
- *     <li>A error uses a return code <code>>=400</code> </li>
- *     <li>All errors use the same result object ({@link org.apache.archiva.rest.api.services.v2.ArchivaRestError}</li>
- *     <li>Error messages are returned as keys. Translation is part of the client application.</li>
- * </ul>
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-package org.apache.archiva.rest.api.services.v2;
\ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Artifact.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Artifact.java
new file mode 100644 (file)
index 0000000..980bab2
--- /dev/null
@@ -0,0 +1,43 @@
+package org.apache.archiva.rest.api.v2.model;
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import java.io.Serializable;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Schema(name="Artifact", description = "Information about artifacts")
+public class Artifact implements Serializable
+{
+    private static final long serialVersionUID = 7581578317346876555L;
+    private String name;
+
+    @Schema(name="name",description = "The name of the artifact")
+    public String getName( )
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ArtifactTransferRequest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ArtifactTransferRequest.java
new file mode 100644 (file)
index 0000000..5a51778
--- /dev/null
@@ -0,0 +1,43 @@
+package org.apache.archiva.rest.api.v2.model;
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import java.io.Serializable;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class ArtifactTransferRequest implements Serializable
+{
+    private static final long serialVersionUID = -7377281345536573342L;
+
+    private String path;
+
+    @Schema(description = "The path to the artifact")
+    public String getPath( )
+    {
+        return path;
+    }
+
+    public void setPath( String path )
+    {
+        this.path = path;
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/BeanInformation.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/BeanInformation.java
new file mode 100644 (file)
index 0000000..0d28a53
--- /dev/null
@@ -0,0 +1,151 @@
+package org.apache.archiva.rest.api.v2.model;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@XmlRootElement(name="beanInformation")
+@Schema(name="BeanInformation",description = "Information about a bean instance.")
+public class BeanInformation implements Serializable
+{
+    private static final long serialVersionUID = -432385743277355987L;
+    private String id;
+    private String displayName;
+    private String descriptionKey;
+    private String defaultDescription;
+    private boolean readonly;
+
+    public BeanInformation( )
+    {
+    }
+
+    public BeanInformation( String id, String displayName, String descriptionKey, String defaultDescription, boolean readonly )
+    {
+        this.id = id;
+        this.displayName = displayName;
+        this.descriptionKey = descriptionKey;
+        this.defaultDescription = defaultDescription;
+        this.readonly = readonly;
+    }
+
+    @Schema(description = "The identifier")
+    public String getId( )
+    {
+        return id;
+    }
+
+    public void setId( String id )
+    {
+        this.id = id;
+    }
+
+    @Schema(name="display_name", description = "The display name")
+    public String getDisplayName( )
+    {
+        return displayName;
+    }
+
+    public void setDisplayName( String displayName )
+    {
+        this.displayName = displayName;
+    }
+
+    @Schema(name="description_key", description = "The translation key for the description")
+    public String getDescriptionKey( )
+    {
+        return descriptionKey;
+    }
+
+    public void setDescriptionKey( String descriptionKey )
+    {
+        this.descriptionKey = descriptionKey;
+    }
+
+    @Schema(name="default_description", description = "The description translated in the default language")
+    public String getDefaultDescription( )
+    {
+        return defaultDescription;
+    }
+
+    public void setDefaultDescription( String defaultDescription )
+    {
+        this.defaultDescription = defaultDescription;
+    }
+
+    @Schema(description = "True, if this bean cannot be removed")
+    public boolean isReadonly( )
+    {
+        return readonly;
+    }
+
+    public void setReadonly( boolean readonly )
+    {
+        this.readonly = readonly;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+        BeanInformation that = (BeanInformation) o;
+        return readonly == that.readonly && id.equals( that.id ) && Objects.equals( displayName, that.displayName ) && Objects.equals( descriptionKey, that.descriptionKey ) && Objects.equals( defaultDescription, that.defaultDescription );
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        return Objects.hash( id, displayName, descriptionKey, defaultDescription, readonly );
+    }
+
+    @Override
+    public String toString( )
+    {
+        return "BeanInformation{" +
+            "id='" + id + '\'' +
+            ", display_name='" + displayName + '\'' +
+            ", description_key='" + descriptionKey + '\'' +
+            ", default_description='" + defaultDescription + '\'' +
+            ", readonly=" + readonly +
+            '}';
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/CacheConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/CacheConfiguration.java
new file mode 100644 (file)
index 0000000..1e58a67
--- /dev/null
@@ -0,0 +1,152 @@
+package org.apache.archiva.rest.api.v2.model;
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+
+/**
+ * @author Olivier Lamy
+ * @author Martin Stockhammer
+ * @since 3.0
+ */
+@XmlRootElement( name = "cacheConfiguration" )
+@Schema(name="CacheConfiguration",description = "Cache configuration attributes")
+public class CacheConfiguration
+    implements Serializable
+{
+    private static final long serialVersionUID = 5479989049980673894L;
+    /**
+     * TimeToIdleSeconds.
+     */
+    private int timeToIdleSeconds = -1;
+
+    /**
+     * TimeToLiveSeconds.
+     */
+    private int timeToLiveSeconds = -1;
+
+    /**
+     * max elements in memory.
+     */
+    private int maxEntriesInMemory = -1;
+
+    /**
+     * max elements on disk.
+     */
+    private int maxEntriesOnDisk = -1;
+
+    public CacheConfiguration()
+    {
+        // no op
+    }
+
+    public static CacheConfiguration of( org.apache.archiva.admin.model.beans.CacheConfiguration beanConfiguration ) {
+        CacheConfiguration newConfig = new CacheConfiguration( );
+        newConfig.setMaxEntriesInMemory( beanConfiguration.getMaxElementsInMemory() );
+        newConfig.setMaxEntriesOnDisk( beanConfiguration.getMaxElementsOnDisk() );
+        newConfig.setTimeToIdleSeconds( beanConfiguration.getTimeToIdleSeconds( ) );
+        newConfig.setTimeToLiveSeconds( beanConfiguration.getTimeToLiveSeconds( ) );
+        return newConfig;
+    }
+
+    @Schema(name="time_to_idle_seconds", description = "The maximum number of seconds an element can exist in the cache without being accessed. "+
+        "The element expires at this limit and will no longer be returned from the cache.")
+    public int getTimeToIdleSeconds()
+    {
+        return timeToIdleSeconds;
+    }
+
+    public void setTimeToIdleSeconds( int timeToIdleSeconds )
+    {
+        this.timeToIdleSeconds = timeToIdleSeconds;
+    }
+
+    @Schema(name="time_to_live_seconds", description = "The maximum number of seconds an element can exist in the cache regardless of use. "+
+        "The element expires at this limit and will no longer be returned from the cache.")
+    public int getTimeToLiveSeconds()
+    {
+        return timeToLiveSeconds;
+    }
+
+    public void setTimeToLiveSeconds( int timeToLiveSeconds )
+    {
+        this.timeToLiveSeconds = timeToLiveSeconds;
+    }
+
+    @Schema(name="max_entries_in_memory", description = "The maximum cache entries to keep in memory. If the limit is reached, older entries will be evicted, or persisted on disk.")
+    public int getMaxEntriesInMemory()
+    {
+        return maxEntriesInMemory;
+    }
+
+    public void setMaxEntriesInMemory( int maxEntriesInMemory )
+    {
+        this.maxEntriesInMemory = maxEntriesInMemory;
+    }
+
+    @Schema(name="max_entries_on_disk", description = "The maximum cache entries to keep on disk. If the limit is reached, older entries will be evicted.")
+    public int getMaxEntriesOnDisk()
+    {
+        return maxEntriesOnDisk;
+    }
+
+    public void setMaxEntriesOnDisk( int maxEntriesOnDisk )
+    {
+        this.maxEntriesOnDisk = maxEntriesOnDisk;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+        CacheConfiguration that = (CacheConfiguration) o;
+
+        if ( timeToIdleSeconds != that.timeToIdleSeconds ) return false;
+        if ( timeToLiveSeconds != that.timeToLiveSeconds ) return false;
+        if ( maxEntriesInMemory != that.maxEntriesInMemory ) return false;
+        return maxEntriesOnDisk == that.maxEntriesOnDisk;
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        int result = timeToIdleSeconds;
+        result = 31 * result + timeToLiveSeconds;
+        result = 31 * result + maxEntriesInMemory;
+        result = 31 * result + maxEntriesOnDisk;
+        return result;
+    }
+
+    @Override
+    public String toString()
+    {
+        final StringBuilder sb = new StringBuilder();
+        sb.append( "CacheConfiguration" );
+        sb.append( "{time_to_idle_seconds=" ).append( timeToIdleSeconds );
+        sb.append( ", time_to_live_seconds=" ).append( timeToLiveSeconds );
+        sb.append( ", max_elements_in_memory=" ).append( maxEntriesInMemory );
+        sb.append( ", max_elements_on_disk=" ).append( maxEntriesOnDisk );
+        sb.append( '}' );
+        return sb.toString();
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/FileInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/FileInfo.java
new file mode 100644 (file)
index 0000000..359d1cb
--- /dev/null
@@ -0,0 +1,132 @@
+package org.apache.archiva.rest.api.v2.model;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.repository.storage.StorageAsset;
+
+import java.io.Serializable;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Schema(name="FileInfo",description = "Information about a file stored in the repository")
+public class FileInfo implements Serializable
+{
+    private static final long serialVersionUID = 900497784542880195L;
+    private OffsetDateTime modified;
+    private String fileName;
+    private String path;
+
+    public FileInfo( )
+    {
+    }
+
+    public static FileInfo of( StorageAsset asset ) {
+        FileInfo fileInfo = new FileInfo( );
+        fileInfo.setFileName( asset.getName() );
+        fileInfo.setPath( asset.getPath() );
+        fileInfo.setModified( asset.getModificationTime( ).atOffset( ZoneOffset.UTC ) );
+        return fileInfo;
+    }
+
+                               @Schema(description = "Time when the file was last modified")
+    public OffsetDateTime getModified( )
+    {
+        return modified;
+    }
+
+    public void setModified( OffsetDateTime modified )
+    {
+        this.modified = modified;
+    }
+
+    @Schema(name="file_name", description = "Name of the file")
+    public String getFileName( )
+    {
+        return fileName;
+    }
+
+    public void setFileName( String fileName )
+    {
+        this.fileName = fileName;
+    }
+
+    @Schema(name="path", description = "Path to the file relative to the repository directory")
+    public String getPath( )
+    {
+        return path;
+    }
+
+    public void setPath( String path )
+    {
+        this.path = path;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+        FileInfo fileInfo = (FileInfo) o;
+
+        if ( modified != null ? !modified.equals( fileInfo.modified ) : fileInfo.modified != null ) return false;
+        if ( fileName != null ? !fileName.equals( fileInfo.fileName ) : fileInfo.fileName != null ) return false;
+        return path != null ? path.equals( fileInfo.path ) : fileInfo.path == null;
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        int result = modified != null ? modified.hashCode( ) : 0;
+        result = 31 * result + ( fileName != null ? fileName.hashCode( ) : 0 );
+        result = 31 * result + ( path != null ? path.hashCode( ) : 0 );
+        return result;
+    }
+
+    @Override
+    public String toString( )
+    {
+        final StringBuilder sb = new StringBuilder( "FileInfo{" );
+        sb.append( "modified=" ).append( modified );
+        sb.append( ", fileName='" ).append( fileName ).append( '\'' );
+        sb.append( ", path='" ).append( path ).append( '\'' );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/IndexingTask.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/IndexingTask.java
new file mode 100644 (file)
index 0000000..42f25cb
--- /dev/null
@@ -0,0 +1,156 @@
+package org.apache.archiva.rest.api.v2.model;
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import java.io.Serializable;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Schema(name="IndexingTask",description = "Information about indexing tasks")
+public class IndexingTask implements Serializable
+{
+    private static final long serialVersionUID = -1947200162602613310L;
+    private String repositoryId = "";
+    private boolean fullRepository;
+    private boolean updateOnly;
+    private String resource = "";
+    private boolean running = false;
+    private long maxExecutionTimeMs = 0;
+
+    public static IndexingTask of( org.apache.archiva.admin.model.beans.IndexingTask repositoryTask ) {
+        IndexingTask indexingTask = new IndexingTask( );
+        indexingTask.setFullRepository( repositoryTask.isFullScan());
+        indexingTask.setUpdateOnly( repositoryTask.isUpdateOnly() );
+        indexingTask.setResource( repositoryTask.getResource() );
+        indexingTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTimeMs() );
+        indexingTask.setRepositoryId( repositoryTask.getRepositoryId() );
+        return indexingTask;
+    }
+
+    @Schema(name="repository_id",description = "Identifier of the repository this task is running on")
+    public String getRepositoryId( )
+    {
+        return repositoryId;
+    }
+
+    public void setRepositoryId( String repositoryId )
+    {
+        this.repositoryId = repositoryId==null?"":repositoryId;
+    }
+
+    @Schema( name = "full_repository", description = "True, if this is a full repository index scan" )
+    public boolean isFullRepository( )
+    {
+        return fullRepository;
+    }
+
+    public void setFullRepository( boolean fullRepository )
+    {
+        this.fullRepository = fullRepository;
+    }
+
+    @Schema(name="update_only", description = "True, if this is only updating the index with new files")
+    public boolean isUpdateOnly( )
+    {
+        return updateOnly;
+    }
+
+    public void setUpdateOnly( boolean updateOnly )
+    {
+        this.updateOnly = updateOnly;
+    }
+
+    @Schema(name="resource",description = "The resource that should be updated, if this is not a full repo update")
+    public String getResource( )
+    {
+        return resource;
+    }
+
+    public void setResource( String resource )
+    {
+        this.resource = resource == null ? "" : resource;
+    }
+
+    @Schema(name="running", description = "True, if this task is currently running")
+    public boolean isRunning( )
+    {
+        return running;
+    }
+
+    public void setRunning( boolean running )
+    {
+        this.running = running;
+    }
+
+    @Schema(name="max_execution_time_ms",description = "Maximum task execution time in ms")
+    public long getMaxExecutionTimeMs( )
+    {
+        return maxExecutionTimeMs;
+    }
+
+    public void setMaxExecutionTimeMs( long maxExecutionTimeMs )
+    {
+        this.maxExecutionTimeMs = maxExecutionTimeMs;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+        IndexingTask that = (IndexingTask) o;
+
+        if ( fullRepository != that.fullRepository ) return false;
+        if ( updateOnly != that.updateOnly ) return false;
+        if ( running != that.running ) return false;
+        if ( maxExecutionTimeMs != that.maxExecutionTimeMs ) return false;
+        if ( !repositoryId.equals( that.repositoryId ) ) return false;
+        return resource.equals( that.resource );
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        int result = repositoryId.hashCode( );
+        result = 31 * result + ( fullRepository ? 1 : 0 );
+        result = 31 * result + ( updateOnly ? 1 : 0 );
+        result = 31 * result + resource.hashCode( );
+        result = 31 * result + ( running ? 1 : 0 );
+        result = 31 * result + (int) ( maxExecutionTimeMs ^ ( maxExecutionTimeMs >>> 32 ) );
+        return result;
+    }
+
+    @Override
+    public String toString( )
+    {
+        final StringBuilder sb = new StringBuilder( "IndexingTask{" );
+        sb.append( "repositoryId='" ).append( repositoryId ).append( '\'' );
+        sb.append( ", fullRepository=" ).append( fullRepository );
+        sb.append( ", updateOnly=" ).append( updateOnly );
+        sb.append( ", resource='" ).append( resource ).append( '\'' );
+        sb.append( ", running=" ).append( running );
+        sb.append( ", maxExecutionTimeMs=" ).append( maxExecutionTimeMs );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/LdapConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/LdapConfiguration.java
new file mode 100644 (file)
index 0000000..15372cd
--- /dev/null
@@ -0,0 +1,327 @@
+package org.apache.archiva.rest.api.v2.model;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.TreeMap;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+@XmlRootElement(name="ldapConfiguration")
+@Schema(name="LdapConfiguration", description = "LDAP configuration attributes")
+public class LdapConfiguration implements Serializable
+{
+    private static final long serialVersionUID = -4736767846016398583L;
+
+    private String hostName = "";
+    private int port = 389;
+    private String baseDn = "";
+    private String groupsBaseDn = "";
+    private String bindDn = "";
+    private String bindPassword = "";
+    private String authenticationMethod = "none";
+    private String contextFactory;
+    private boolean sslEnabled = false;
+    private boolean bindAuthenticatorEnabled = true;
+    private boolean useRoleNameAsGroup = false;
+    private Map<String, String> properties = new TreeMap<>();
+    private boolean writable = false;
+    private List<String> availableContextFactories;
+
+    public LdapConfiguration( )
+    {
+    }
+
+    public static LdapConfiguration of( org.apache.archiva.admin.model.beans.LdapConfiguration ldapConfiguration ) {
+        LdapConfiguration newCfg = new LdapConfiguration( );
+        newCfg.setAuthenticationMethod( ldapConfiguration.getAuthenticationMethod( ) );
+        newCfg.setBaseDn( ldapConfiguration.getBaseDn( ) );
+        newCfg.setGroupsBaseDn( ldapConfiguration.getBaseGroupsDn() );
+        newCfg.setBindDn( ldapConfiguration.getBindDn() );
+        newCfg.setBindPassword( ldapConfiguration.getPassword() );
+        newCfg.setBindAuthenticatorEnabled( ldapConfiguration.isBindAuthenticatorEnabled() );
+        newCfg.setHostName( ldapConfiguration.getHostName( ) );
+        newCfg.setSslEnabled( ldapConfiguration.isSsl() );
+        newCfg.setContextFactory( ldapConfiguration.getContextFactory() );
+        if (ldapConfiguration.getPort()<=0) {
+            newCfg.setPort( newCfg.isSslEnabled() ? 636 : 389 );
+        } else
+        {
+            newCfg.setPort( ldapConfiguration.getPort( ) );
+        }
+        newCfg.setProperties( ldapConfiguration.getExtraProperties( ) );
+        newCfg.setWritable( ldapConfiguration.isWritable() );
+        return newCfg;
+    }
+
+    @Schema(name="host_name", description = "The hostname to use to connect to the LDAP server")
+    public String getHostName( )
+    {
+        return hostName;
+    }
+
+    public void setHostName( String hostName )
+    {
+        this.hostName = hostName==null?"":hostName;
+    }
+
+    @Schema(description = "The port to use to connect to the LDAP server")
+    public int getPort( )
+    {
+        return port;
+    }
+
+    public void setPort( int port )
+    {
+        this.port = port;
+    }
+
+    @Schema(name="context_factory",description = "The class name of the LDAP context factory")
+    public String getContextFactory( )
+    {
+        return contextFactory;
+    }
+
+    public void setContextFactory( String contextFactory )
+    {
+        this.contextFactory = contextFactory;
+    }
+
+
+    @Schema(name="ssl_enabled", description = "True, if SSL/TLS should be used for connecting the LDAP server")
+    public boolean isSslEnabled( )
+    {
+        return sslEnabled;
+    }
+
+    public void setSslEnabled( boolean sslEnabled )
+    {
+        this.sslEnabled = sslEnabled;
+    }
+
+    @Schema(name="base_dn", description = "The BASE DN used for the LDAP server")
+    public String getBaseDn( )
+    {
+        return baseDn;
+    }
+
+    public void setBaseDn( String baseDn )
+    {
+        this.baseDn = baseDn == null ? "" : baseDn;
+    }
+
+    @Schema(name="bind_dn", description = "The distinguished name of the bind user which is used to bind to the LDAP server")
+    public String getBindDn( )
+    {
+        return bindDn;
+    }
+
+    public void setBindDn( String bindDn )
+    {
+        this.bindDn = bindDn == null ? "" : bindDn;
+    }
+
+    @Schema(name="bind_password", description = "The password used to bind to the ldap server")
+    public String getBindPassword( )
+    {
+        return bindPassword;
+    }
+
+    public void setBindPassword( String bindPassword )
+    {
+        this.bindPassword = bindPassword==null?"":bindPassword;
+    }
+
+    @Schema(name="groups_base_dn", description = "The distinguished name of the base to use for searching group.")
+    public String getGroupsBaseDn( )
+    {
+        return groupsBaseDn;
+    }
+
+    public void setGroupsBaseDn( String groupsBaseDn )
+    {
+        this.groupsBaseDn = groupsBaseDn==null?"":groupsBaseDn;
+    }
+
+    @Schema(name="authentication_method", description = "The authentication method used to bind to the LDAP server (PLAINTEXT, SASL, ...)")
+    public String getAuthenticationMethod( )
+    {
+        return authenticationMethod;
+    }
+
+    public void setAuthenticationMethod( String authenticationMethod )
+    {
+        this.authenticationMethod = authenticationMethod==null?"":authenticationMethod;
+    }
+
+    @Schema(name="bind_authenticator_enabled", description = "True, if the LDAP bind authentication is used for logging in to Archiva")
+    public boolean isBindAuthenticatorEnabled( )
+    {
+        return bindAuthenticatorEnabled;
+    }
+
+    public void setBindAuthenticatorEnabled( boolean bindAuthenticatorEnabled )
+    {
+        this.bindAuthenticatorEnabled = bindAuthenticatorEnabled;
+    }
+
+    @Schema(name="user_role_name_as_group", description = "True, if the archiva role name is also the LDAP group name")
+    public boolean isUseRoleNameAsGroup( )
+    {
+        return useRoleNameAsGroup;
+    }
+
+    public void setUseRoleNameAsGroup( boolean useRoleNameAsGroup )
+    {
+        this.useRoleNameAsGroup = useRoleNameAsGroup;
+    }
+
+    @Schema(description = "LDAP ConnectionFactory environment properties")
+    public Map<String, String> getProperties( )
+    {
+        return properties;
+    }
+
+    public void setProperties( Map<String, String> properties )
+    {
+        this.properties = new TreeMap<>( properties  );
+    }
+
+    public void addProperty(String key, String value) {
+        this.properties.put( key, value );
+    }
+
+    @Schema(description = "True, if attributes in the the LDAP server can be edited by Archiva")
+    public boolean isWritable( )
+    {
+        return writable;
+    }
+
+    public void setWritable( boolean writable )
+    {
+        this.writable = writable;
+    }
+
+    @Schema(name="available_context_factories", description = "The LDAP context factories that are known and available")
+    public List<String> getAvailableContextFactories( )
+    {
+        return availableContextFactories;
+    }
+
+    public void setAvailableContextFactories( List<String> availableContextFactories )
+    {
+        this.availableContextFactories = new ArrayList<>( availableContextFactories );
+    }
+
+    public void addAvailableContextFactory(String contextFactory) {
+        if (!this.availableContextFactories.contains( contextFactory ) ) {
+            this.availableContextFactories.add( contextFactory );
+        }
+    }
+
+
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+        LdapConfiguration that = (LdapConfiguration) o;
+
+        if ( port != that.port ) return false;
+        if ( sslEnabled != that.sslEnabled ) return false;
+        if ( bindAuthenticatorEnabled != that.bindAuthenticatorEnabled ) return false;
+        if ( useRoleNameAsGroup != that.useRoleNameAsGroup ) return false;
+        if ( writable != that.writable ) return false;
+        if ( !Objects.equals( hostName, that.hostName ) ) return false;
+        if ( !Objects.equals( baseDn, that.baseDn ) ) return false;
+        if ( !Objects.equals( bindDn, that.bindDn ) ) return false;
+        if ( !Objects.equals( groupsBaseDn, that.groupsBaseDn ) )
+            return false;
+        if ( !Objects.equals( bindPassword, that.bindPassword ) ) return false;
+        if ( !Objects.equals( authenticationMethod, that.authenticationMethod ) )
+            return false;
+        return properties.equals( that.properties );
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        int result = hostName != null ? hostName.hashCode( ) : 0;
+        result = 31 * result + port;
+        result = 31 * result + ( sslEnabled ? 1 : 0 );
+        result = 31 * result + ( baseDn != null ? baseDn.hashCode( ) : 0 );
+        result = 31 * result + ( bindDn != null ? bindDn.hashCode( ) : 0 );
+        result = 31 * result + ( groupsBaseDn != null ? groupsBaseDn.hashCode( ) : 0 );
+        result = 31 * result + ( bindPassword != null ? bindPassword.hashCode( ) : 0 );
+        result = 31 * result + ( authenticationMethod != null ? authenticationMethod.hashCode( ) : 0 );
+        result = 31 * result + ( bindAuthenticatorEnabled ? 1 : 0 );
+        result = 31 * result + ( useRoleNameAsGroup ? 1 : 0 );
+        result = 31 * result + properties.hashCode( );
+        result = 31 * result + ( writable ? 1 : 0 );
+        return result;
+    }
+
+    @SuppressWarnings( "StringBufferReplaceableByString" )
+    @Override
+    public String toString( )
+    {
+        final StringBuilder sb = new StringBuilder( "LdapConfiguration{" );
+        sb.append( "host_name='" ).append( hostName ).append( '\'' );
+        sb.append( ", port=" ).append( port );
+        sb.append( ", ssl_enabled=" ).append( sslEnabled );
+        sb.append( ", base_dn='" ).append( baseDn ).append( '\'' );
+        sb.append( ", groups_base_dn='" ).append( groupsBaseDn ).append( '\'' );
+        sb.append( ", bind_dn='" ).append( bindDn ).append( '\'' );
+        sb.append( ", bind_password='" ).append( bindPassword ).append( '\'' );
+        sb.append( ", authentication_method='" ).append( authenticationMethod ).append( '\'' );
+        sb.append( ", bind_authenticator_enabled=" ).append( bindAuthenticatorEnabled );
+        sb.append( ", use_role_name_as_group=" ).append( useRoleNameAsGroup );
+        sb.append( ", properties=" ).append( properties );
+        sb.append( ", writable=" ).append( writable );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepository.java
new file mode 100644 (file)
index 0000000..e82db10
--- /dev/null
@@ -0,0 +1,264 @@
+package org.apache.archiva.rest.api.v2.model;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.features.ArtifactCleanupFeature;
+import org.apache.archiva.repository.features.IndexCreationFeature;
+import org.apache.archiva.repository.features.StagingRepositoryFeature;
+
+import java.time.Period;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Schema(name="MavenManagedRepository",description = "A managed repository stores artifacts locally")
+public class MavenManagedRepository extends Repository
+{
+    private static final long serialVersionUID = -6853748886201905029L;
+
+    boolean blocksRedeployments;
+    List<String> releaseSchemes = new ArrayList<>(  );
+    boolean deleteSnapshotsOfRelease = false;
+    private Period retentionPeriod;
+    private int retentionCount;
+    private String indexPath;
+    private String packedIndexPath;
+    private boolean skipPackedIndexCreation;
+    private boolean hasStagingRepository;
+    private String stagingRepository;
+
+
+    public MavenManagedRepository( )
+    {
+        super.setCharacteristic( Repository.CHARACTERISTIC_MANAGED );
+        super.setType( RepositoryType.MAVEN.name( ) );
+    }
+
+    protected static void update(MavenManagedRepository repo, ManagedRepository beanRepo) {
+        repo.setDescription( beanRepo.getDescription() );
+        repo.setId( beanRepo.getId() );
+        repo.setIndex( true );
+        repo.setLayout( beanRepo.getLayout() );
+        repo.setBlocksRedeployments( beanRepo.blocksRedeployments() );
+        repo.setReleaseSchemes( beanRepo.getActiveReleaseSchemes().stream().map( Objects::toString).collect( Collectors.toList()) );
+        repo.setLocation( beanRepo.getLocation().toString() );
+        repo.setName( beanRepo.getName());
+        repo.setScanned( beanRepo.isScanned() );
+        repo.setSchedulingDefinition( beanRepo.getSchedulingDefinition() );
+        ArtifactCleanupFeature artifactCleanupFeature = beanRepo.getFeature( ArtifactCleanupFeature.class ).get( );
+        repo.setDeleteSnapshotsOfRelease( artifactCleanupFeature.isDeleteReleasedSnapshots());
+        repo.setRetentionCount( artifactCleanupFeature.getRetentionCount());
+        repo.setRetentionPeriod( artifactCleanupFeature.getRetentionPeriod() );
+        IndexCreationFeature icf = beanRepo.getFeature( IndexCreationFeature.class ).get( );
+        repo.setIndex( icf.hasIndex( ) );
+        repo.setIndexPath( icf.getIndexPath( ).getPath( ) );
+        repo.setPackedIndexPath( icf.getPackedIndexPath( ).getPath( ) );
+        repo.setSkipPackedIndexCreation( icf.isSkipPackedIndexCreation() );
+        StagingRepositoryFeature srf = beanRepo.getFeature( StagingRepositoryFeature.class ).get( );
+        repo.setHasStagingRepository( srf.isStageRepoNeeded( ) );
+        repo.setStagingRepository( srf.getStagingRepository()!=null?srf.getStagingRepository().getId():"" );
+    }
+
+    public static MavenManagedRepository of( ManagedRepository beanRepo ) {
+        MavenManagedRepository repo = new MavenManagedRepository( );
+        update( repo, beanRepo );
+        return repo;
+    }
+
+    @Schema(name="blocks_redeployments",description = "True, if redeployments to this repository are not allowed")
+    public boolean isBlocksRedeployments( )
+    {
+        return blocksRedeployments;
+    }
+
+    public void setBlocksRedeployments( boolean blocksRedeployments )
+    {
+        this.blocksRedeployments = blocksRedeployments;
+    }
+
+    @Schema(name="release_schemes", description = "The release schemes this repository is used for (e.g. RELEASE, SNAPSHOT)")
+    public List<String> getReleaseSchemes( )
+    {
+        return releaseSchemes;
+    }
+
+    public void setReleaseSchemes( List<String> releaseSchemes )
+    {
+        this.releaseSchemes = new ArrayList<>( releaseSchemes );
+    }
+
+    public void addReleaseScheme(String scheme) {
+        if (!this.releaseSchemes.contains( scheme ))
+        {
+            this.releaseSchemes.add( scheme );
+        }
+    }
+
+    @Schema(name="delete_snaphots_of_release", description = "True, if snapshots are deleted, after a version is released")
+    public boolean isDeleteSnapshotsOfRelease( )
+    {
+        return deleteSnapshotsOfRelease;
+    }
+
+    public void setDeleteSnapshotsOfRelease( boolean deleteSnapshotsOfRelease )
+    {
+        this.deleteSnapshotsOfRelease = deleteSnapshotsOfRelease;
+    }
+
+    @Schema(name="retention_period", description = "The period after which snapshots are deleted.")
+    public Period getRetentionPeriod( )
+    {
+        return retentionPeriod;
+    }
+
+    public void setRetentionPeriod( Period retentionPeriod )
+    {
+        this.retentionPeriod = retentionPeriod;
+    }
+
+    @Schema(name="retention_count", description = "Number of snapshot artifacts to keep.")
+    public int getRetentionCount( )
+    {
+        return retentionCount;
+    }
+
+    public void setRetentionCount( int retentionCount )
+    {
+        this.retentionCount = retentionCount;
+    }
+
+    @Schema( name = "index_path", description = "Path to the directory that contains the index, relative to the repository base directory" )
+    public String getIndexPath( )
+    {
+        return indexPath;
+    }
+
+    public void setIndexPath( String indexPath )
+    {
+        this.indexPath = indexPath;
+    }
+
+    @Schema( name = "packed_index_path", description = "Path to the directory that contains the packed index, relative to the repository base directory" )
+    public String getPackedIndexPath( )
+    {
+        return packedIndexPath;
+    }
+
+    public void setPackedIndexPath( String packedIndexPath )
+    {
+        this.packedIndexPath = packedIndexPath;
+    }
+
+    @Schema(name="skip_packed_index_creation", description = "True, if packed index is not created during index update")
+    public boolean isSkipPackedIndexCreation( )
+    {
+        return skipPackedIndexCreation;
+    }
+
+    public void setSkipPackedIndexCreation( boolean skipPackedIndexCreation )
+    {
+        this.skipPackedIndexCreation = skipPackedIndexCreation;
+    }
+
+    @Schema(name="has_staging_repository", description = "True, if this repository has a staging repository assigned")
+    public boolean isHasStagingRepository( )
+    {
+        return hasStagingRepository;
+    }
+
+    public void setHasStagingRepository( boolean hasStagingRepository )
+    {
+        this.hasStagingRepository = hasStagingRepository;
+    }
+
+    @Schema(name="staging_repository", description = "The id of the assigned staging repository")
+    public String getStagingRepository( )
+    {
+        return stagingRepository;
+    }
+
+    public void setStagingRepository( String stagingRepository )
+    {
+        this.stagingRepository = stagingRepository;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+        if ( !super.equals( o ) ) return false;
+
+        MavenManagedRepository that = (MavenManagedRepository) o;
+
+        if ( blocksRedeployments != that.blocksRedeployments ) return false;
+        return releaseSchemes != null ? releaseSchemes.equals( that.releaseSchemes ) : that.releaseSchemes == null;
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        int result = super.hashCode( );
+        result = 31 * result + ( blocksRedeployments ? 1 : 0 );
+        result = 31 * result + ( releaseSchemes != null ? releaseSchemes.hashCode( ) : 0 );
+        return result;
+    }
+
+    @Override
+    public String toString( )
+    {
+        final StringBuilder sb = new StringBuilder( "ManagedRepository{" );
+        sb.append( "blocksRedeployments=" ).append( blocksRedeployments );
+        sb.append( ", releaseSchemes=" ).append( releaseSchemes );
+        sb.append( ", id='" ).append( id ).append( '\'' );
+        sb.append( ", name='" ).append( name ).append( '\'' );
+        sb.append( ", description='" ).append( description ).append( '\'' );
+        sb.append( ", type='" ).append( type ).append( '\'' );
+        sb.append( ", location='" ).append( location ).append( '\'' );
+        sb.append( ", scanned=" ).append( scanned );
+        sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' );
+        sb.append( ", index=" ).append( index );
+        sb.append( ", layout='" ).append( layout ).append( '\'' );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepositoryUpdate.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepositoryUpdate.java
new file mode 100644 (file)
index 0000000..5536ae9
--- /dev/null
@@ -0,0 +1,47 @@
+package org.apache.archiva.rest.api.v2.model;
+/*
+ * 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.repository.ManagedRepository;
+
+import java.io.Serializable;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class MavenManagedRepositoryUpdate extends MavenManagedRepository implements Serializable
+{
+    private static final long serialVersionUID = -9181643343284109862L;
+    private boolean resetStats = false;
+
+    public static MavenManagedRepositoryUpdate of( ManagedRepository repository ) {
+        MavenManagedRepositoryUpdate repo = new MavenManagedRepositoryUpdate( );
+        update( repo, repository );
+        return repo;
+    }
+
+    public boolean isResetStats( )
+    {
+        return resetStats;
+    }
+
+    public void setResetStats( boolean resetStats )
+    {
+        this.resetStats = resetStats;
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenRemoteRepository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenRemoteRepository.java
new file mode 100644 (file)
index 0000000..8375ede
--- /dev/null
@@ -0,0 +1,168 @@
+package org.apache.archiva.rest.api.v2.model;
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+@Schema(name="MavenRemoteRepository",description = "A remote repository definition is used to pull artifacts from other repositories")
+public class MavenRemoteRepository extends Repository
+{
+    private static final long serialVersionUID = 5625043398766480265L;
+    String loginUser;
+    String loginPassword;
+    String checkPath;
+    Map<String,String> extraParameters = new TreeMap<>(  );
+    Map<String,String> requestHeader = new TreeMap<>(  );
+    long timeoutMs;
+
+    @Schema(name="login_user",description = "Username for login to the remote repository")
+    public String getLoginUser( )
+    {
+        return loginUser;
+    }
+
+    public void setLoginUser( String loginUser )
+    {
+        this.loginUser = loginUser;
+    }
+
+    @Schema(name="login_password",description = "Password for connecting to the remote repository")
+    public String getLoginPassword( )
+    {
+        return loginPassword;
+    }
+
+    public void setLoginPassword( String loginPassword )
+    {
+        this.loginPassword = loginPassword;
+    }
+
+    @Schema(name="check_path",description = "Path relative to the repository URL that is used to check of availability of the remote repository.")
+    public String getCheckPath( )
+    {
+        return checkPath;
+    }
+
+    public void setCheckPath( String checkPath )
+    {
+        this.checkPath = checkPath;
+    }
+
+    @Schema(name="extra_parameters", description = "Key-Value map with extra parameters sent to the remote repository")
+    public Map<String, String> getExtraParameters( )
+    {
+        return extraParameters;
+    }
+
+    public void setExtraParameters( Map<String, String> extraParameters )
+    {
+        this.extraParameters = new TreeMap<>( extraParameters );
+    }
+
+    public void addExtraParameter(String key, String value) {
+        this.extraParameters.put( key, value );
+    }
+
+    @Schema(name="request_header",description = "Key-Value map with request headers that are sent to the remote repository")
+    public Map<String, String> getRequestHeader( )
+    {
+        return requestHeader;
+    }
+
+    public void setRequestHeader( Map<String, String> requestHeader )
+    {
+        this.requestHeader = new TreeMap<>( requestHeader );
+    }
+
+    public void addRequestHeader(String headerName, String headerValue) {
+        this.requestHeader.put( headerName, headerValue );
+    }
+
+    @Schema(name="timeout_ms", description = "The time in milliseconds after that a request to the remote repository is aborted")
+    public long getTimeoutMs( )
+    {
+        return timeoutMs;
+    }
+
+    public void setTimeoutMs( long timeoutMs )
+    {
+        this.timeoutMs = timeoutMs;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+        if ( !super.equals( o ) ) return false;
+
+        MavenRemoteRepository that = (MavenRemoteRepository) o;
+
+        if ( timeoutMs != that.timeoutMs ) return false;
+        if ( loginUser != null ? !loginUser.equals( that.loginUser ) : that.loginUser != null ) return false;
+        if ( loginPassword != null ? !loginPassword.equals( that.loginPassword ) : that.loginPassword != null )
+            return false;
+        if ( checkPath != null ? !checkPath.equals( that.checkPath ) : that.checkPath != null ) return false;
+        if ( extraParameters != null ? !extraParameters.equals( that.extraParameters ) : that.extraParameters != null )
+            return false;
+        return requestHeader != null ? requestHeader.equals( that.requestHeader ) : that.requestHeader == null;
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        int result = super.hashCode( );
+        result = 31 * result + ( loginUser != null ? loginUser.hashCode( ) : 0 );
+        result = 31 * result + ( loginPassword != null ? loginPassword.hashCode( ) : 0 );
+        result = 31 * result + ( checkPath != null ? checkPath.hashCode( ) : 0 );
+        result = 31 * result + ( extraParameters != null ? extraParameters.hashCode( ) : 0 );
+        result = 31 * result + ( requestHeader != null ? requestHeader.hashCode( ) : 0 );
+        result = 31 * result + (int) ( timeoutMs ^ ( timeoutMs >>> 32 ) );
+        return result;
+    }
+
+    @Override
+    public String toString( )
+    {
+        final StringBuilder sb = new StringBuilder( "RemoteRepository{" );
+        sb.append( "loginUser='" ).append( loginUser ).append( '\'' );
+        sb.append( ", loginPassword='" ).append( loginPassword ).append( '\'' );
+        sb.append( ", checkPath='" ).append( checkPath ).append( '\'' );
+        sb.append( ", extraParameters=" ).append( extraParameters );
+        sb.append( ", requestHeader=" ).append( requestHeader );
+        sb.append( ", timeOut=" ).append( timeoutMs );
+        sb.append( ", id='" ).append( id ).append( '\'' );
+        sb.append( ", name='" ).append( name ).append( '\'' );
+        sb.append( ", description='" ).append( description ).append( '\'' );
+        sb.append( ", type='" ).append( type ).append( '\'' );
+        sb.append( ", location='" ).append( location ).append( '\'' );
+        sb.append( ", scanned=" ).append( scanned );
+        sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' );
+        sb.append( ", index=" ).append( index );
+        sb.append( ", layout='" ).append( layout ).append( '\'' );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MergeConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MergeConfiguration.java
new file mode 100644 (file)
index 0000000..053e129
--- /dev/null
@@ -0,0 +1,128 @@
+package org.apache.archiva.rest.api.v2.model;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.Objects;
+
+import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
+
+/**
+ * Index merge configuration.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+@XmlRootElement(name="mergeConfiguration")
+@Schema(name="MergeConfiguration", description = "Configuration settings for index merge of remote repositories.")
+public class MergeConfiguration implements Serializable
+{
+    private static final long serialVersionUID = -3629274059574459133L;
+
+    private String mergedIndexPath = DEFAULT_INDEX_PATH;
+    private int mergedIndexTtlMinutes = 30;
+    private String indexMergeSchedule = "";
+
+    @Schema(name="merged_index_path", description = "The path where the merged index is stored. The path is relative to the repository directory of the group.")
+    public String getMergedIndexPath( )
+    {
+        return mergedIndexPath;
+    }
+
+    public void setMergedIndexPath( String mergedIndexPath )
+    {
+        this.mergedIndexPath = mergedIndexPath;
+    }
+
+    @Schema(name="merged_index_ttl_minutes", description = "The Time to Life of the merged index in minutes.")
+    public int getMergedIndexTtlMinutes( )
+    {
+        return mergedIndexTtlMinutes;
+    }
+
+    public void setMergedIndexTtlMinutes( int mergedIndexTtlMinutes )
+    {
+        this.mergedIndexTtlMinutes = mergedIndexTtlMinutes;
+    }
+
+    @Schema(name="index_merge_schedule", description = "Cron expression that defines the times/intervals for index merging.")
+    public String getIndexMergeSchedule( )
+    {
+        return indexMergeSchedule;
+    }
+
+    public void setIndexMergeSchedule( String indexMergeSchedule )
+    {
+        this.indexMergeSchedule = indexMergeSchedule;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+        MergeConfiguration that = (MergeConfiguration) o;
+
+        if ( mergedIndexTtlMinutes != that.mergedIndexTtlMinutes ) return false;
+        if ( !Objects.equals( mergedIndexPath, that.mergedIndexPath ) )
+            return false;
+        return Objects.equals( indexMergeSchedule, that.indexMergeSchedule );
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        int result = mergedIndexPath != null ? mergedIndexPath.hashCode( ) : 0;
+        result = 31 * result + mergedIndexTtlMinutes;
+        result = 31 * result + ( indexMergeSchedule != null ? indexMergeSchedule.hashCode( ) : 0 );
+        return result;
+    }
+
+    @SuppressWarnings( "StringBufferReplaceableByString" )
+    @Override
+    public String toString( )
+    {
+        final StringBuilder sb = new StringBuilder( "MergeConfiguration{" );
+        sb.append( "mergedIndexPath='" ).append( mergedIndexPath ).append( '\'' );
+        sb.append( ", mergedIndexTtlMinutes=" ).append( mergedIndexTtlMinutes );
+        sb.append( ", indexMergeSchedule='" ).append( indexMergeSchedule ).append( '\'' );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Repository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Repository.java
new file mode 100644 (file)
index 0000000..d097964
--- /dev/null
@@ -0,0 +1,289 @@
+package org.apache.archiva.rest.api.v2.model;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.RemoteRepository;
+
+import java.io.Serializable;
+import java.util.Locale;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+@Schema(description = "Repository data")
+public class Repository implements Serializable
+{
+    private static final long serialVersionUID = -4741025877287175182L;
+
+    public static final String CHARACTERISTIC_MANAGED = "managed";
+    public static final String CHARACTERISTIC_REMOTE = "remote";
+    public static final String CHARACTERISTIC_UNKNOWN = "unknown";
+
+    protected String id;
+    protected String name;
+    protected String description;
+    protected String type;
+    protected String characteristic;
+    protected String location;
+    protected boolean scanned;
+    protected String schedulingDefinition;
+    protected boolean index;
+    protected String layout;
+
+    public Repository( )
+    {
+    }
+
+    public static Repository of( org.apache.archiva.repository.Repository repository ) {
+        Repository newRepo = new Repository( );
+        newRepo.setId( repository.getId() );
+        newRepo.setName( repository.getName( ) );
+        newRepo.setDescription( repository.getDescription( ) );
+        newRepo.setLocation( repository.getLocation().toASCIIString() );
+        newRepo.setIndex( repository.hasIndex() );
+        newRepo.setLayout( repository.getLayout() );
+        newRepo.setType( repository.getType().name() );
+        newRepo.setScanned( repository.isScanned() );
+        newRepo.setSchedulingDefinition( repository.getSchedulingDefinition() );
+        if (repository instanceof RemoteRepository ) {
+            newRepo.setCharacteristic( CHARACTERISTIC_REMOTE );
+        } else if (repository instanceof ManagedRepository ) {
+            newRepo.setCharacteristic( CHARACTERISTIC_MANAGED );
+        } else {
+            newRepo.setCharacteristic( CHARACTERISTIC_UNKNOWN );
+        }
+        return newRepo;
+    }
+
+    public static Repository of( org.apache.archiva.repository.Repository repository, Locale locale ) {
+        Locale myLocale;
+        if (locale==null) {
+            myLocale = Locale.getDefault( );
+        } 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( repoName );
+        newRepo.setDescription( description );
+        newRepo.setLocation( repository.getLocation().toASCIIString() );
+        newRepo.setIndex( repository.hasIndex() );
+        newRepo.setLayout( repository.getLayout() );
+        newRepo.setType( repository.getType().name() );
+        newRepo.setScanned( repository.isScanned() );
+        newRepo.setSchedulingDefinition( repository.getSchedulingDefinition() );
+        if (repository instanceof RemoteRepository ) {
+            newRepo.setCharacteristic( CHARACTERISTIC_REMOTE );
+        } else if (repository instanceof ManagedRepository ) {
+            newRepo.setCharacteristic( CHARACTERISTIC_MANAGED );
+        } else {
+            newRepo.setCharacteristic( CHARACTERISTIC_UNKNOWN );
+        }
+        return newRepo;
+    }
+
+    @Schema(description = "Category of the repository. Either 'managed' or 'remote'.")
+    public String getCharacteristic( )
+    {
+        return characteristic;
+    }
+
+    public void setCharacteristic( String characteristic )
+    {
+        this.characteristic = characteristic;
+    }
+
+    @Schema(description = "Unique identifier of the repository")
+    public String getId( )
+    {
+        return id;
+    }
+
+    public void setId( String id )
+    {
+        this.id = id;
+    }
+
+    @Schema(description = "Display name of the repository")
+    public String getName( )
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    @Schema(description = "Description of the repository")
+    public String getDescription( )
+    {
+        return description;
+    }
+
+    public void setDescription( String description )
+    {
+        this.description = description;
+    }
+
+    @Schema(description = "Repository type")
+    public String getType( )
+    {
+        return type;
+    }
+
+    public void setType( String type )
+    {
+        this.type = type;
+    }
+
+    @Schema(description = "The location, where the repository data can be found")
+    public String getLocation( )
+    {
+        return location;
+    }
+
+    public void setLocation( String location )
+    {
+        this.location = location;
+    }
+
+    @Schema(description = "True, if this repository is scanned regularly")
+    public boolean isScanned( )
+    {
+        return scanned;
+    }
+
+    public void setScanned( boolean scanned )
+    {
+        this.scanned = scanned;
+    }
+
+    @Schema(name="scheduling_definition",description = "Definition of regular scheduled scan")
+    public String getSchedulingDefinition( )
+    {
+        return schedulingDefinition;
+    }
+
+    public void setSchedulingDefinition( String schedulingDefinition )
+    {
+        this.schedulingDefinition = schedulingDefinition;
+    }
+
+    @Schema(description = "True, if this is a indexed repository")
+    public boolean isIndex( )
+    {
+        return index;
+    }
+
+    public void setIndex( boolean index )
+    {
+        this.index = index;
+    }
+
+    @Schema(description = "Layout type is implementation specific")
+    public String getLayout( )
+    {
+        return layout;
+    }
+
+    public void setLayout( String layout )
+    {
+        this.layout = layout;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+        Repository that = (Repository) o;
+
+        if ( scanned != that.scanned ) return false;
+        if ( index != that.index ) return false;
+        if ( id != null ? !id.equals( that.id ) : that.id != null ) return false;
+        if ( name != null ? !name.equals( that.name ) : that.name != null ) return false;
+        if ( description != null ? !description.equals( that.description ) : that.description != null ) return false;
+        if ( type != null ? !type.equals( that.type ) : that.type != null ) return false;
+        if ( location != null ? !location.equals( that.location ) : that.location != null ) return false;
+        if ( schedulingDefinition != null ? !schedulingDefinition.equals( that.schedulingDefinition ) : that.schedulingDefinition != null )
+            return false;
+        return layout != null ? layout.equals( that.layout ) : that.layout == null;
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        int result = id != null ? id.hashCode( ) : 0;
+        result = 31 * result + ( name != null ? name.hashCode( ) : 0 );
+        result = 31 * result + ( description != null ? description.hashCode( ) : 0 );
+        result = 31 * result + ( type != null ? type.hashCode( ) : 0 );
+        result = 31 * result + ( location != null ? location.hashCode( ) : 0 );
+        result = 31 * result + ( scanned ? 1 : 0 );
+        result = 31 * result + ( schedulingDefinition != null ? schedulingDefinition.hashCode( ) : 0 );
+        result = 31 * result + ( index ? 1 : 0 );
+        result = 31 * result + ( layout != null ? layout.hashCode( ) : 0 );
+        return result;
+    }
+
+    @Override
+    public String toString( )
+    {
+        final StringBuilder sb = new StringBuilder( "Repository{" );
+        sb.append( "id='" ).append( id ).append( '\'' );
+        sb.append( ", name='" ).append( name ).append( '\'' );
+        sb.append( ", description='" ).append( description ).append( '\'' );
+        sb.append( ", type='" ).append( type ).append( '\'' );
+        sb.append( ", location='" ).append( location ).append( '\'' );
+        sb.append( ", scanned=" ).append( scanned );
+        sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' );
+        sb.append( ", index=" ).append( index );
+        sb.append( ", layout='" ).append( layout ).append( '\'' );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryGroup.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryGroup.java
new file mode 100644 (file)
index 0000000..6f64a51
--- /dev/null
@@ -0,0 +1,176 @@
+package org.apache.archiva.rest.api.v2.model;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.features.IndexCreationFeature;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@XmlRootElement(name="repositoryGroup")
+@Schema(name="RepositoryGroup", description = "Information about a repository group, which combines multiple repositories as one virtual repository.")
+public class RepositoryGroup implements Serializable
+{
+    private static final long serialVersionUID = -7319687481737616081L;
+    private String id;
+    private String name;
+    private List<String> repositories = new ArrayList<>(  );
+    private String location;
+    MergeConfiguration mergeConfiguration;
+
+    public RepositoryGroup( )
+    {
+    }
+
+    public RepositoryGroup(String id) {
+        this.id = id;
+    }
+
+    public static RepositoryGroup of( org.apache.archiva.repository.RepositoryGroup modelObj ) {
+        RepositoryGroup result = new RepositoryGroup( );
+        MergeConfiguration mergeConfig = new MergeConfiguration( );
+        result.setMergeConfiguration( mergeConfig );
+        result.setId( modelObj.getId() );
+        result.setName( modelObj.getName() );
+        result.setLocation( modelObj.getLocation().toString() );
+        result.setRepositories( modelObj.getRepositories().stream().map( Repository::getId ).collect( Collectors.toList()) );
+        if (modelObj.supportsFeature( IndexCreationFeature.class )) {
+            IndexCreationFeature icf = modelObj.getFeature( IndexCreationFeature.class ).get();
+            mergeConfig.setMergedIndexPath( icf.getIndexPath( ).toString() );
+            mergeConfig.setMergedIndexTtlMinutes( modelObj.getMergedIndexTTL( ) );
+            mergeConfig.setIndexMergeSchedule( modelObj.getSchedulingDefinition() );
+        }
+        return result;
+    }
+
+    @Schema(description = "The unique id of the repository group.")
+    public String getId( )
+    {
+        return id;
+    }
+
+    public void setId( String id )
+    {
+        this.id = id;
+    }
+
+    @Schema(description = "The list of ids of repositories which are member of the repository group.")
+    public List<String> getRepositories( )
+    {
+        return repositories;
+    }
+
+    public void setRepositories( List<String> repositories )
+    {
+        this.repositories = new ArrayList<>( repositories );
+    }
+
+    public void addRepository(String repositoryId) {
+        if (!this.repositories.contains( repositoryId )) {
+            this.repositories.add( repositoryId );
+        }
+    }
+
+    @Schema(name="merge_configuration",description = "The configuration for index merge.")
+    public MergeConfiguration getMergeConfiguration( )
+    {
+        return mergeConfiguration;
+    }
+
+    public void setMergeConfiguration( MergeConfiguration mergeConfiguration )
+    {
+        this.mergeConfiguration = mergeConfiguration;
+    }
+
+    @Schema(description = "The storage location of the repository. The merged index is stored relative to this location.")
+    public String getLocation( )
+    {
+        return location;
+    }
+
+    public void setLocation( String location )
+    {
+        this.location = location;
+    }
+
+    @Schema(description = "The name of the repository group")
+    public String getName( )
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+        RepositoryGroup that = (RepositoryGroup) o;
+
+        return id.equals( that.id );
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        return id.hashCode( );
+    }
+
+    @Override
+    public String toString( )
+    {
+        final StringBuilder sb = new StringBuilder( "RepositoryGroup{" );
+        sb.append( "id='" ).append( id ).append( '\'' );
+        sb.append( ", name='" ).append( name ).append( '\'' );
+        sb.append( ", repositories=" ).append( repositories );
+        sb.append( ", location='" ).append( location ).append( '\'' );
+        sb.append( ", mergeConfiguration=" ).append( mergeConfiguration );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryStatistics.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryStatistics.java
new file mode 100644 (file)
index 0000000..ab2c916
--- /dev/null
@@ -0,0 +1,291 @@
+package org.apache.archiva.rest.api.v2.model;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.repository.scanner.RepositoryScanStatistics;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.time.Duration;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+@XmlRootElement(name="repositoryStatistics")
+@Schema(name="RepositoryStatistics", description = "Statistics data")
+public class RepositoryStatistics implements Serializable
+{
+    private static final long serialVersionUID = 7943367882738452531L;
+
+    private OffsetDateTime scanEndTime;
+    private OffsetDateTime scanStartTime;
+    private long scanDurationMs;
+    private long totalArtifactCount;
+    private long totalArtifactFileSize;
+    private long totalFileCount;
+    private long totalGroupCount;
+    private long totalProjectCount;
+    private long newFileCount;
+    private Map<String, Long> totalCountForType = new TreeMap<>(  );
+    private Map<String, Long> customValues = new TreeMap<>(  );
+
+    public RepositoryStatistics( )
+    {
+    }
+
+    public static RepositoryStatistics of( org.apache.archiva.metadata.repository.stats.model.RepositoryStatistics modelStats ) {
+        RepositoryStatistics newStats = new RepositoryStatistics( );
+        newStats.setScanStartTime( modelStats.getScanStartTime().toInstant().atOffset( ZoneOffset.UTC ) );
+        newStats.setScanEndTime( modelStats.getScanEndTime( ).toInstant( ).atOffset( ZoneOffset.UTC ) );
+        newStats.setNewFileCount( modelStats.getNewFileCount() );
+        newStats.setScanDurationMs( Duration.between( newStats.scanStartTime, newStats.scanEndTime ).toMillis() );
+        newStats.setTotalArtifactCount( modelStats.getTotalArtifactCount() );
+        newStats.setTotalArtifactFileSize( modelStats.getTotalArtifactFileSize() );
+        newStats.setTotalCountForType( modelStats.getTotalCountForType() );
+        newStats.setTotalFileCount( modelStats.getTotalFileCount() );
+        newStats.setTotalGroupCount( modelStats.getTotalGroupCount() );
+        newStats.setTotalProjectCount( modelStats.getTotalProjectCount() );
+        for (String key : modelStats.getAvailableCustomValues()) {
+            newStats.addCustomValue( key, modelStats.getCustomValue( key ) );
+        }
+        return newStats;
+    }
+
+    public static RepositoryStatistics of( RepositoryScanStatistics scanStatistics ) {
+        RepositoryStatistics newStats = new RepositoryStatistics( );
+        newStats.setScanStartTime( scanStatistics.getWhenGathered().toInstant().atOffset( ZoneOffset.UTC ) );
+        newStats.setScanEndTime( OffsetDateTime.now(ZoneOffset.UTC) );
+        newStats.setNewFileCount( scanStatistics.getNewFileCount() );
+        newStats.setScanDurationMs( Duration.between( newStats.scanStartTime, newStats.scanEndTime ).toMillis() );
+        newStats.setTotalArtifactCount( scanStatistics.getTotalFileCount() );
+        newStats.setTotalArtifactFileSize( scanStatistics.getTotalSize() );
+        newStats.setTotalFileCount( scanStatistics.getTotalFileCount() );
+        newStats.setTotalGroupCount( 0 );
+        newStats.setTotalProjectCount( 0 );
+        return newStats;
+    }
+
+    @Schema(name="scan_end_time", description = "Date and time when the last scan finished")
+    public OffsetDateTime getScanEndTime( )
+    {
+        return scanEndTime;
+    }
+
+    public void setScanEndTime( OffsetDateTime scanEndTime )
+    {
+        this.scanEndTime = scanEndTime;
+    }
+
+    @Schema( name = "scan_start_time", description = "Date and time when the last scan started" )
+    public OffsetDateTime getScanStartTime( )
+    {
+        return scanStartTime;
+    }
+
+    public void setScanStartTime( OffsetDateTime scanStartTime )
+    {
+        this.scanStartTime = scanStartTime;
+    }
+
+    @Schema(name="total_artifact_count", description = "The number of artifacts scanned")
+    public long getTotalArtifactCount( )
+    {
+        return totalArtifactCount;
+    }
+
+    public void setTotalArtifactCount( long totalArtifactCount )
+    {
+        this.totalArtifactCount = totalArtifactCount;
+    }
+
+    @Schema(name="total_artifact_file_size", description = "The cumulative size of all files scanned")
+    public long getTotalArtifactFileSize( )
+    {
+        return totalArtifactFileSize;
+    }
+
+    public void setTotalArtifactFileSize( long totalArtifactFileSize )
+    {
+        this.totalArtifactFileSize = totalArtifactFileSize;
+    }
+
+    @Schema(name="total_file_count", description = "The total number of files scanned")
+    public long getTotalFileCount( )
+    {
+        return totalFileCount;
+    }
+
+    public void setTotalFileCount( long totalFileCount )
+    {
+        this.totalFileCount = totalFileCount;
+    }
+
+    @Schema(name="total_group_count", description = "The number of groups scanned")
+    public long getTotalGroupCount( )
+    {
+        return totalGroupCount;
+    }
+
+    public void setTotalGroupCount( long totalGroupCount )
+    {
+        this.totalGroupCount = totalGroupCount;
+    }
+
+    @Schema(name="total_project_count", description = "The number of projects scanned")
+    public long getTotalProjectCount( )
+    {
+        return totalProjectCount;
+    }
+
+    public void setTotalProjectCount( long totalProjectCount )
+    {
+        this.totalProjectCount = totalProjectCount;
+    }
+
+    @Schema(name="new_file_count", description = "Number of files registered as new")
+    public long getNewFileCount( )
+    {
+        return newFileCount;
+    }
+
+    public void setNewFileCount( long newFileCount )
+    {
+        this.newFileCount = newFileCount;
+    }
+
+    @Schema(name="scan_duration_ms", description = "The duration of the last scan in ms")
+    public long getScanDurationMs( )
+    {
+        return scanDurationMs;
+    }
+
+    public void setScanDurationMs( long scanDurationMs )
+    {
+        this.scanDurationMs = scanDurationMs;
+    }
+
+    @Schema(name="total_count_for_type", description = "File counts partitioned by file types")
+    public Map<String, Long> getTotalCountForType( )
+    {
+        return totalCountForType;
+    }
+
+    public void setTotalCountForType( Map<String, Long> totalCountForType )
+    {
+        this.totalCountForType = new TreeMap<>( totalCountForType );
+    }
+
+    public void addTotalCountForType( String type, Long value )
+    {
+        this.totalCountForType.put( type, value );
+    }
+
+    @Schema(name="custom_values", description = "Custom statistic values")
+    public Map<String, Long> getCustomValues( )
+    {
+        return customValues;
+    }
+
+    public void setCustomValues( Map<String, Long> customValues )
+    {
+        this.customValues = new TreeMap<>(  customValues );
+    }
+
+    public void addCustomValue(String type, Long value) {
+        this.customValues.put( type, value );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+        RepositoryStatistics that = (RepositoryStatistics) o;
+
+        if ( scanDurationMs != that.scanDurationMs ) return false;
+        if ( totalArtifactCount != that.totalArtifactCount ) return false;
+        if ( totalArtifactFileSize != that.totalArtifactFileSize ) return false;
+        if ( totalFileCount != that.totalFileCount ) return false;
+        if ( totalGroupCount != that.totalGroupCount ) return false;
+        if ( totalProjectCount != that.totalProjectCount ) return false;
+        if ( newFileCount != that.newFileCount ) return false;
+        if ( scanEndTime != null ? !scanEndTime.equals( that.scanEndTime ) : that.scanEndTime != null ) return false;
+        if ( scanStartTime != null ? !scanStartTime.equals( that.scanStartTime ) : that.scanStartTime != null )
+            return false;
+        if ( !totalCountForType.equals( that.totalCountForType ) ) return false;
+        return customValues.equals( that.customValues );
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        int result = scanEndTime != null ? scanEndTime.hashCode( ) : 0;
+        result = 31 * result + ( scanStartTime != null ? scanStartTime.hashCode( ) : 0 );
+        result = 31 * result + (int) ( scanDurationMs ^ ( scanDurationMs >>> 32 ) );
+        result = 31 * result + (int) ( totalArtifactCount ^ ( totalArtifactCount >>> 32 ) );
+        result = 31 * result + (int) ( totalArtifactFileSize ^ ( totalArtifactFileSize >>> 32 ) );
+        result = 31 * result + (int) ( totalFileCount ^ ( totalFileCount >>> 32 ) );
+        result = 31 * result + (int) ( totalGroupCount ^ ( totalGroupCount >>> 32 ) );
+        result = 31 * result + (int) ( totalProjectCount ^ ( totalProjectCount >>> 32 ) );
+        result = 31 * result + (int) ( newFileCount ^ ( newFileCount >>> 32 ) );
+        result = 31 * result + totalCountForType.hashCode( );
+        result = 31 * result + customValues.hashCode( );
+        return result;
+    }
+
+    @Override
+    public String toString( )
+    {
+        final StringBuilder sb = new StringBuilder( "RepositoryStatistics{" );
+        sb.append( "scanEndTime=" ).append( scanEndTime );
+        sb.append( ", scanStartTime=" ).append( scanStartTime );
+        sb.append( ", scanDurationMs=" ).append( scanDurationMs );
+        sb.append( ", totalArtifactCount=" ).append( totalArtifactCount );
+        sb.append( ", totalArtifactFileSize=" ).append( totalArtifactFileSize );
+        sb.append( ", totalFileCount=" ).append( totalFileCount );
+        sb.append( ", totalGroupCount=" ).append( totalGroupCount );
+        sb.append( ", totalProjectCount=" ).append( totalProjectCount );
+        sb.append( ", newFileCount=" ).append( newFileCount );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanStatus.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanStatus.java
new file mode 100644 (file)
index 0000000..4e46594
--- /dev/null
@@ -0,0 +1,124 @@
+package org.apache.archiva.rest.api.v2.model;
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.admin.model.beans.MetadataScanTask;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Schema(name="ScanStatus", description = "Status of repository scan tasks")
+public class ScanStatus implements Serializable
+{
+    private boolean scanRunning = false;
+    private int scanQueued = 0;
+    private boolean indexRunning = false;
+    private int indexQueued = 0;
+    private List<IndexingTask> indexingQueue = new ArrayList<>(  );
+    private List<ScanTask> scanQueue = new ArrayList<>(  );
+
+    public ScanStatus( )
+    {
+    }
+
+    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;
+
+    }
+
+    @Schema( name = "scan_running", description = "True, if a scan is currently running" )
+    public boolean isScanRunning( )
+    {
+        return scanRunning;
+    }
+
+    public void setScanRunning( boolean scanRunning )
+    {
+        this.scanRunning = scanRunning;
+    }
+
+    @Schema(name ="scan_queued", description = "Number of scans in the task queue")
+    public int getScanQueued( )
+    {
+        return scanQueued;
+    }
+
+    public void setScanQueued( int scanQueued )
+    {
+        this.scanQueued = scanQueued;
+    }
+
+    @Schema(name="index_running", description = "True, if there is a index task currently running")
+    public boolean isIndexRunning( )
+    {
+        return indexRunning;
+    }
+
+    public void setIndexRunning( boolean indexRunning )
+    {
+        this.indexRunning = indexRunning;
+    }
+
+    @Schema(name="index_queued", description = "Number of queued index tasks")
+    public int getIndexQueued( )
+    {
+        return indexQueued;
+    }
+
+    public void setIndexQueued( int indexQueued )
+    {
+        this.indexQueued = indexQueued;
+    }
+
+    @Schema( name = "indexing_queue", description = "List of indexing tasks waiting for execution" )
+    public List<IndexingTask> getIndexingQueue( )
+    {
+        return indexingQueue;
+    }
+
+    public void setIndexingQueue( List<IndexingTask> indexingQueue )
+    {
+        this.indexingQueue = new ArrayList<>( indexingQueue );
+    }
+
+    @Schema(name="scan_queue", description = "List of scan tasks waiting for execution")
+    public List<ScanTask> getScanQueue( )
+    {
+        return scanQueue;
+    }
+
+    public void setScanQueue( List<ScanTask> scanQueue )
+    {
+        this.scanQueue = new ArrayList<>( scanQueue );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanTask.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanTask.java
new file mode 100644 (file)
index 0000000..15e42d8
--- /dev/null
@@ -0,0 +1,156 @@
+package org.apache.archiva.rest.api.v2.model;
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.admin.model.beans.MetadataScanTask;
+
+import java.io.Serializable;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Schema(name="ScanTask", description = "Repository scan task information")
+public class ScanTask implements Serializable
+{
+    private static final long serialVersionUID = -681163357370848098L;
+    private String repositoryId="";
+    private boolean updateRelatedArtifacts;
+    private boolean fullRepository;
+    private boolean running = false;
+    private String resource = "";
+    private long maxExecutionTimeMs = 0;
+
+    public static ScanTask of( MetadataScanTask repositoryTask ) {
+        ScanTask scanTask = new ScanTask( );
+        scanTask.setFullRepository( repositoryTask.isFullScan());
+        scanTask.setUpdateRelatedArtifacts( repositoryTask.isUpdateRelatedArtifacts() );
+        scanTask.setResource( repositoryTask.getResource() );
+        scanTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTimeMs() );
+        scanTask.setRepositoryId( repositoryTask.getRepositoryId( ) );
+        return scanTask;
+    }
+
+    @Schema(name="repository_id", description = "Identifier of the repository, this task is running on")
+    public String getRepositoryId( )
+    {
+        return repositoryId;
+    }
+
+    public void setRepositoryId( String repositoryId )
+    {
+        this.repositoryId = repositoryId==null?"":repositoryId;
+    }
+
+    @Schema(name="update_related_artifacts", description = "True, if related artifacts are updated too.")
+    public boolean isUpdateRelatedArtifacts( )
+    {
+        return updateRelatedArtifacts;
+    }
+
+    public void setUpdateRelatedArtifacts( boolean updateRelatedArtifacts )
+    {
+        this.updateRelatedArtifacts = updateRelatedArtifacts;
+    }
+
+    @Schema(name="full_repository",description = "True, if this is a full repository scan")
+    public boolean isFullRepository( )
+    {
+        return fullRepository;
+    }
+
+    public void setFullRepository( boolean fullRepository )
+    {
+        this.fullRepository = fullRepository;
+    }
+
+    @Schema(name="running", description = "True, if this task is currently running")
+    public boolean isRunning( )
+    {
+        return running;
+    }
+
+    public void setRunning( boolean running )
+    {
+        this.running = running;
+    }
+
+    @Schema(name="resource",description = "Name of the resource to update")
+    public String getResource( )
+    {
+        return resource;
+    }
+
+    public void setResource( String resource )
+    {
+        this.resource = resource==null?"":resource;
+    }
+
+    @Schema(name="max_excecution_time_ms",description = "Maximum execution time in ms")
+    public long getMaxExecutionTimeMs( )
+    {
+        return maxExecutionTimeMs;
+    }
+
+    public void setMaxExecutionTimeMs( long maxExecutionTimeMs )
+    {
+        this.maxExecutionTimeMs = maxExecutionTimeMs;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+        ScanTask scanTask = (ScanTask) o;
+
+        if ( updateRelatedArtifacts != scanTask.updateRelatedArtifacts ) return false;
+        if ( fullRepository != scanTask.fullRepository ) 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 + ( fullRepository ? 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( fullRepository );
+        sb.append( ", running=" ).append( running );
+        sb.append( ", resource='" ).append( resource ).append( '\'' );
+        sb.append( ", maxExecutionTimeMs=" ).append( maxExecutionTimeMs );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/SecurityConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/SecurityConfiguration.java
new file mode 100644 (file)
index 0000000..a3c0629
--- /dev/null
@@ -0,0 +1,179 @@
+package org.apache.archiva.rest.api.v2.model;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.admin.model.beans.RedbackRuntimeConfiguration;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@XmlRootElement(name = "securityConfiguration")
+@Schema(name = "SecurityConfiguration", description = "Security configuration attributes.")
+public class SecurityConfiguration implements Serializable
+{
+    private static final long serialVersionUID = -4186866365979053029L;
+
+    private List<String> activeUserManagers = new ArrayList<>(  );
+    private List<String> activeRbacManagers = new ArrayList<>(  );
+    private Map<String,String> properties = new TreeMap<>(  );
+    private boolean userCacheEnabled=false;
+    private boolean ldapActive=false;
+
+    public SecurityConfiguration() {
+
+    }
+
+    public static SecurityConfiguration ofRedbackConfiguration( RedbackRuntimeConfiguration configuration ) {
+        SecurityConfiguration secConfig = new SecurityConfiguration( );
+        secConfig.setActiveRbacManagers( configuration.getRbacManagerImpls() );
+        secConfig.setActiveUserManagers( configuration.getUserManagerImpls() );
+        secConfig.setProperties( configuration.getConfigurationProperties() );
+        boolean rbLdapActive = configuration.getUserManagerImpls( ).stream( ).anyMatch( um -> um.contains( "ldap" ) );
+        secConfig.setLdapActive( rbLdapActive );
+        secConfig.setUserCacheEnabled( configuration.isUseUsersCache() );
+        return secConfig;
+    }
+
+    @Schema(name="active_user_managers", description = "List of ids of the active user managers")
+    public List<String> getActiveUserManagers( )
+    {
+        return activeUserManagers;
+    }
+
+    public void setActiveUserManagers( List<String> activeUserManagers )
+    {
+        this.activeUserManagers = new ArrayList<>( activeUserManagers );
+    }
+
+    public void addSelectedUserManager(String userManager) {
+        this.activeUserManagers.add( userManager );
+    }
+
+    @Schema(name="active_rbac_managers", description = "List of ids of the active rbac managers")
+    public List<String> getActiveRbacManagers( )
+    {
+        return activeRbacManagers;
+    }
+
+    public void setActiveRbacManagers( List<String> activeRbacManagers )
+    {
+        this.activeRbacManagers = new ArrayList<>( activeRbacManagers );
+    }
+
+    public void addSelectedRbacManager(String rbacManager) {
+        this.activeRbacManagers.add( rbacManager );
+    }
+
+    @Schema(description = "Map of all security properties")
+    public Map<String, String> getProperties( )
+    {
+        return properties;
+    }
+
+    public void setProperties( Map<String, String> properties )
+    {
+        this.properties = new TreeMap<>( properties );
+    }
+
+    @Schema(name="user_cache_enabled", description = "True, if the user cache is active. It caches data from user backend.")
+    public boolean isUserCacheEnabled( )
+    {
+        return userCacheEnabled;
+    }
+
+    public void setUserCacheEnabled( boolean userCacheEnabled )
+    {
+        this.userCacheEnabled = userCacheEnabled;
+    }
+
+    @Schema(name="ldap_active", description = "True, if LDAP is used as user manager")
+    public boolean isLdapActive( )
+    {
+        return ldapActive;
+    }
+
+    public void setLdapActive( boolean ldapActive )
+    {
+        this.ldapActive = ldapActive;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+        SecurityConfiguration that = (SecurityConfiguration) o;
+
+        if ( userCacheEnabled != that.userCacheEnabled ) return false;
+        if ( ldapActive != that.ldapActive ) return false;
+        if ( !activeUserManagers.equals( that.activeUserManagers ) ) return false;
+        if ( !activeRbacManagers.equals( that.activeRbacManagers ) ) return false;
+        return properties.equals( that.properties );
+    }
+
+    @Override
+    public int hashCode( )
+    {
+        int result = activeUserManagers.hashCode( );
+        result = 31 * result + activeRbacManagers.hashCode( );
+        result = 31 * result + properties.hashCode( );
+        result = 31 * result + ( userCacheEnabled ? 1 : 0 );
+        result = 31 * result + ( ldapActive ? 1 : 0 );
+        return result;
+    }
+
+    @SuppressWarnings( "StringBufferReplaceableByString" )
+    @Override
+    public String toString( )
+    {
+        final StringBuilder sb = new StringBuilder( "SecurityConfiguration{" );
+        sb.append( "active_user_managers=" ).append( activeUserManagers );
+        sb.append( ", active_rbac_managers=" ).append( activeRbacManagers );
+        sb.append( ", properties=" ).append( properties );
+        sb.append( ", user_cache_enabled=" ).append( userCacheEnabled );
+        sb.append( ", ldap_active=" ).append( ldapActive );
+        sb.append( '}' );
+        return sb.toString( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ValidationError.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ValidationError.java
new file mode 100644 (file)
index 0000000..d8e51cb
--- /dev/null
@@ -0,0 +1,139 @@
+package org.apache.archiva.rest.api.v2.model;
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@XmlRootElement(name = "validationError")
+@Schema(name = "ValidationError", description = "A validation error.")
+public class ValidationError implements Serializable
+{
+    private static final long serialVersionUID = 2079020598090660171L;
+
+    String key;
+    String field;
+    String category;
+    String type;
+    List<String> parameter;
+
+
+    public ValidationError( )
+    {
+    }
+
+    public ValidationError( String key, String field, String category, String type, List<String> parameter) {
+        this.key = key;
+        this.field = field;
+        this.category = category;
+        this.type = type;
+        if (parameter==null) {
+            this.parameter = new ArrayList<>( );
+        } else
+        {
+            this.parameter = parameter;
+        }
+    }
+
+    /**
+     * Creates a new instance based on the given error
+     * @param error the error instance
+     * @return
+     */
+    public static ValidationError of( org.apache.archiva.repository.validation.ValidationError error ) {
+        return error != null ? new ValidationError( error.getErrorKey( ), error.getAttribute( ), error.getCategory( ),
+            error.getType( ), error.getArguments( ).stream( ).map( Object::toString ).collect( Collectors.toList( ) ) )
+            : new ValidationError( );
+    }
+
+    /**
+     * Creates a new instance based on the field name and the error instance
+     * @param fieldName the name of the field to which the error applies
+     * @param error the error definition
+     * @return a new validation error instance
+     */
+    public static ValidationError of( String fieldName, org.apache.archiva.repository.validation.ValidationError error ) {
+        return error != null ? new ValidationError( error.getErrorKey( ), fieldName, error.getCategory( ),
+            error.getType( ), error.getArguments( ).stream( ).map( Object::toString ).collect( Collectors.toList( ) ) )
+            : new ValidationError( );
+    }
+
+    @Schema(name="key", description = "The full key of the validation error")
+    public String getKey( )
+    {
+        return key;
+    }
+
+    public void setKey( String key )
+    {
+        this.key = key;
+    }
+
+    @Schema(name="field", description = "The name of the field where the error was detected")
+    public String getField( )
+    {
+        return field;
+    }
+
+    public void setField( String field )
+    {
+        this.field = field;
+    }
+
+    @Schema(name="category", description = "The name of the category this error is assigned to")
+    public String getCategory( )
+    {
+        return category;
+    }
+
+    public void setCategory( String category )
+    {
+        this.category = category;
+    }
+
+    @Schema(name="type", description = "The type of the error. This is a unique string that defines the type of error, e.g. empty, bad_number_range, ... .")
+    public String getType( )
+    {
+        return type;
+    }
+
+    public void setType( String type )
+    {
+        this.type = type;
+    }
+
+    @Schema(name="parameter", description = "The list of parameters, that can be used to create a translated error message")
+    public List<String> getParameter( )
+    {
+        return parameter;
+    }
+
+    public void setParameter( List<String> parameter )
+    {
+        this.parameter = parameter;
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/ArtifactCleanupInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/ArtifactCleanupInfo.java
new file mode 100644 (file)
index 0000000..145d390
--- /dev/null
@@ -0,0 +1,83 @@
+package org.apache.archiva.rest.api.v2.model.repository;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import java.time.Period;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Schema(name="ArtifactCleanupInfo",description = "Information for artifact cleanup feature of repository")
+public class ArtifactCleanupInfo
+{
+    boolean deleteReleasedSnapshots;
+    Period retentionPeriod;
+    int retentionCount;
+
+    @Schema(name="delete_released_snapshots",description = "True, if snapshots are deleted after a release was published")
+    public boolean isDeleteReleasedSnapshots( )
+    {
+        return deleteReleasedSnapshots;
+    }
+
+    public void setDeleteReleasedSnapshots( boolean deleteReleasedSnapshots )
+    {
+        this.deleteReleasedSnapshots = deleteReleasedSnapshots;
+    }
+
+    @Schema(name="retention_period",description = "Time, after that snapshot artifacts are marked for deletion")
+    public Period getRetentionPeriod( )
+    {
+        return retentionPeriod;
+    }
+
+    public void setRetentionPeriod( Period retentionPeriod )
+    {
+        this.retentionPeriod = retentionPeriod;
+    }
+
+    @Schema(name="retention_count",description = "Maximum number of snapshot artifacts to keep")
+    public int getRetentionCount( )
+    {
+        return retentionCount;
+    }
+
+    public void setRetentionCount( int retentionCount )
+    {
+        this.retentionCount = retentionCount;
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/IndexCreationInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/IndexCreationInfo.java
new file mode 100644 (file)
index 0000000..276dea8
--- /dev/null
@@ -0,0 +1,81 @@
+package org.apache.archiva.rest.api.v2.model.repository;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Schema(name="IndexCreationInfo",description = "Information about index creation feature of repositories")
+public class IndexCreationInfo
+{
+    private boolean skipPackedIndexCreation = false;
+    private String indexPath;
+    private String packedIndexPath;
+
+    @Schema(name="skip_packed_index_creation",description = "True, if the packed index will not be created")
+    public boolean isSkipPackedIndexCreation( )
+    {
+        return skipPackedIndexCreation;
+    }
+
+    public void setSkipPackedIndexCreation( boolean skipPackedIndexCreation )
+    {
+        this.skipPackedIndexCreation = skipPackedIndexCreation;
+    }
+
+    @Schema(name="index_path",description = "Path to the index directory relative to the repository base directory")
+    public String getIndexPath( )
+    {
+        return indexPath;
+    }
+
+    public void setIndexPath( String indexPath )
+    {
+        this.indexPath = indexPath;
+    }
+
+    @Schema(name="packed_index_path",description = "Path to the packed index directory relative to the repository base directory")
+    public String getPackedIndexPath( )
+    {
+        return packedIndexPath;
+    }
+
+    public void setPackedIndexPath( String packedIndexPath )
+    {
+        this.packedIndexPath = packedIndexPath;
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/RemoteIndexInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/RemoteIndexInfo.java
new file mode 100644 (file)
index 0000000..e2ee855
--- /dev/null
@@ -0,0 +1,69 @@
+package org.apache.archiva.rest.api.v2.model.repository;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Schema(name="RemoteIndexInfo",description = "Information about remote indexes")
+public class RemoteIndexInfo
+{
+    private boolean downloadRemoteIndex = false;
+    private String indexUri;
+
+    @Schema(name="download_remote_index",description = "True, if the index will be downloaded from the remote repository")
+    public boolean isDownloadRemoteIndex( )
+    {
+        return downloadRemoteIndex;
+    }
+
+    public void setDownloadRemoteIndex( boolean downloadRemoteIndex )
+    {
+        this.downloadRemoteIndex = downloadRemoteIndex;
+    }
+
+    @Schema(name="index_uri", description = "The URI that specifies the path to the remote index")
+    public String getIndexUri( )
+    {
+        return indexUri;
+    }
+
+    public void setIndexUri( String indexUri )
+    {
+        this.indexUri = indexUri;
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/StagingInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/StagingInfo.java
new file mode 100644 (file)
index 0000000..cd0f0db
--- /dev/null
@@ -0,0 +1,69 @@
+package org.apache.archiva.rest.api.v2.model.repository;/*
+ * 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.
+ */
+
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Schema(name="StagingInfo",description = "Information about staging feature of a repository")
+public class StagingInfo
+{
+    private String stagingRepository;
+    private boolean stageRepoNeeded;
+
+    @Schema(name="staging_repo",description = "The repository id of the staging repository")
+    public String getStagingRepository( )
+    {
+        return stagingRepository;
+    }
+
+    public void setStagingRepository( String stagingRepository )
+    {
+        this.stagingRepository = stagingRepository;
+    }
+
+    @Schema(name="stage_repo_needed",description = "True, if this repository needs a staging repository")
+    public boolean isStageRepoNeeded( )
+    {
+        return stageRepoNeeded;
+    }
+
+    public void setStageRepoNeeded( boolean stageRepoNeeded )
+    {
+        this.stageRepoNeeded = stageRepoNeeded;
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestError.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestError.java
new file mode 100644 (file)
index 0000000..7444d73
--- /dev/null
@@ -0,0 +1,97 @@
+package org.apache.archiva.rest.api.v2.svc;
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.rest.api.v2.model.ValidationError;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Martin Stockhammer
+ * @since 3.0
+ */
+@XmlRootElement( name = "archivaRestError" )
+@Schema(name="ArchivaRestError", description = "Contains a list of error messages that resulted from the current REST call")
+public class ArchivaRestError
+    implements Serializable
+{
+
+    private static final long serialVersionUID = -8892617571273167067L;
+    private List<ErrorMessage> errorMessages = new ArrayList<>( 1 );
+    private List<ValidationError> validationErrors;
+
+    public ArchivaRestError()
+    {
+        // no op
+    }
+
+    public ArchivaRestError( ArchivaRestServiceException e )
+    {
+        errorMessages.addAll( e.getErrorMessages() );
+        if ( e.getErrorMessages().isEmpty() && StringUtils.isNotEmpty( e.getMessage() ) )
+        {
+            errorMessages.add( new ErrorMessage( e.getMessage(), null ) );
+        }
+        if (e instanceof ValidationException) {
+            this.validationErrors = ( (ValidationException) e ).getValidationErrors( );
+        }
+    }
+
+    public ArchivaRestError( ValidationException e )
+    {
+        errorMessages.addAll( e.getErrorMessages() );
+        if ( e.getErrorMessages().isEmpty() && StringUtils.isNotEmpty( e.getMessage() ) )
+        {
+            errorMessages.add( new ErrorMessage( e.getMessage(), null ) );
+        }
+        this.validationErrors = e.getValidationErrors( );
+    }
+
+    @Schema(name="error_messages", description = "The list of errors that occurred while processing the REST request")
+    public List<ErrorMessage> getErrorMessages()
+    {
+        return errorMessages;
+    }
+
+    public void setErrorMessages( List<ErrorMessage> errorMessages )
+    {
+        this.errorMessages = errorMessages;
+    }
+
+    public void addErrorMessage( ErrorMessage errorMessage )
+    {
+        this.errorMessages.add( errorMessage );
+    }
+
+    @Schema( name = "has_validation_errors", description = "True, if the error contains validation errors" )
+    public boolean hasValidationErrors( )
+    {
+        return this.validationErrors != null && this.validationErrors.size( ) > 0;
+    }
+
+    @Schema( name = "validation_errors", description = "The list of validation errors")
+    public List<ValidationError> getValidationErrors() {
+        return hasValidationErrors() ? this.validationErrors : Collections.emptyList( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestServiceException.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestServiceException.java
new file mode 100644 (file)
index 0000000..19f50df
--- /dev/null
@@ -0,0 +1,97 @@
+package org.apache.archiva.rest.api.v2.svc;
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+
+/**
+ * Generic REST Service Exception that contains error information.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+public class ArchivaRestServiceException extends Exception
+{
+    private int httpErrorCode = 500;
+
+    private List<ErrorMessage> errorMessages = new ArrayList<ErrorMessage>(0);
+
+    public ArchivaRestServiceException( String s )
+    {
+        super( s );
+    }
+
+    public ArchivaRestServiceException( String s, int httpErrorCode )
+    {
+        super( s );
+        this.httpErrorCode = httpErrorCode;
+    }
+
+    public ArchivaRestServiceException( ErrorMessage errorMessage )
+    {
+        errorMessages.add( errorMessage );
+    }
+
+    public ArchivaRestServiceException( ErrorMessage errorMessage, int httpResponseCode )
+    {
+        this.httpErrorCode = httpResponseCode;
+        errorMessages.add( errorMessage );
+    }
+
+    public ArchivaRestServiceException( List<ErrorMessage> errorMessage )
+    {
+        errorMessages.addAll( errorMessage );
+    }
+
+    public ArchivaRestServiceException( List<ErrorMessage> errorMessage, int httpResponseCode )
+    {
+        this.httpErrorCode = httpResponseCode;
+        errorMessages.addAll( errorMessage );
+    }
+
+    public int getHttpErrorCode()
+    {
+        return httpErrorCode;
+    }
+
+    public void setHttpErrorCode( int httpErrorCode )
+    {
+        this.httpErrorCode = httpErrorCode;
+    }
+
+    public List<ErrorMessage> getErrorMessages()
+    {
+        if ( errorMessages == null )
+        {
+            this.errorMessages = new ArrayList<ErrorMessage>();
+        }
+        return errorMessages;
+    }
+
+    public void setErrorMessages( List<ErrorMessage> errorMessages )
+    {
+        this.errorMessages = errorMessages;
+    }
+
+    public void addErrorMessage( ErrorMessage errorMessage )
+    {
+        this.errorMessages.add( errorMessage );
+    }
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorKeys.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorKeys.java
new file mode 100644 (file)
index 0000000..cc0a836
--- /dev/null
@@ -0,0 +1,125 @@
+package org.apache.archiva.rest.api.v2.svc;/*
+ * 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.
+ */
+
+/*
+ * 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.
+ */
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public interface ErrorKeys
+{
+
+    String PREFIX = "archiva.";
+
+    String VALIDATION_ERROR = PREFIX + "validation_error";
+
+    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";
+    String LDAP_CF_INIT_FAILED = "archiva.ldap.cf.init.failed";
+    String LDAP_USER_MAPPER_INIT_FAILED = "archiva.ldap.usermapper.init.failed";
+    String LDAP_COMMUNICATION_ERROR = "archiva.ldap.communication_error";
+    String LDAP_INVALID_NAME = "archiva.ldap.invalid_name";
+    String LDAP_GENERIC_ERROR = "archiva.ldap.generic_error";
+    String LDAP_SERVICE_UNAVAILABLE = "archiva.ldap.service_unavailable";
+    String LDAP_SERVICE_AUTHENTICATION_FAILED = "archiva.ldap.authentication.failed";
+    String LDAP_SERVICE_AUTHENTICATION_NOT_SUPPORTED = "archiva.ldap.authentication.not_supported";
+    String LDAP_SERVICE_NO_PERMISSION = "archiva.ldap.no_permissions";
+
+    String PROPERTY_NOT_FOUND = "archiva.property.not.found";
+
+    String MISSING_DATA = "archiva.missing.data";
+
+    String REPOSITORY_GROUP_NOT_FOUND = REPOSITORY_GROUP_PREFIX+"notfound";
+    String REPOSITORY_GROUP_ADD_FAILED = REPOSITORY_GROUP_PREFIX+"add.failed"  ;
+    String REPOSITORY_GROUP_EXIST = REPOSITORY_GROUP_PREFIX+"exists";
+    String REPOSITORY_GROUP_UPDATE_FAILED = REPOSITORY_GROUP_PREFIX + "update.failed";
+
+    String REPOSITORY_GROUP_DELETE_FAILED = REPOSITORY_GROUP_PREFIX + "delete.failed";
+    String REPOSITORY_NOT_FOUND = REPOSITORY_PREFIX + "notfound";
+    String REPOSITORY_MANAGED_NOT_FOUND = REPOSITORY_PREFIX + "managed.notfound";
+    String REPOSITORY_REMOTE_NOT_FOUND = REPOSITORY_PREFIX + "remote.notfound";
+
+    String REPOSITORY_METADATA_ERROR = REPOSITORY_PREFIX + "metadata_error";
+
+    String TASK_QUEUE_FAILED = PREFIX + "task.queue_failed";
+    String REPOSITORY_SCAN_FAILED = REPOSITORY_PREFIX + "scan.failed";
+    String ARTIFACT_EXISTS_AT_DEST = REPOSITORY_PREFIX + "artifact.dest.exists";
+    String REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED = REPOSITORY_PREFIX + "remote.index.download_failed";
+    String REPOSITORY_WRONG_TYPE = REPOSITORY_PREFIX + "wrong_type";
+    String REPOSITORY_DELETE_FAILED = REPOSITORY_PREFIX + "delete.failed";
+    String REPOSITORY_INVALID_ID = REPOSITORY_PREFIX + "invalid.id";
+    String REPOSITORY_ID_EXISTS = REPOSITORY_PREFIX + "id.exists";
+    String REPOSITORY_UPDATE_FAILED = REPOSITORY_PREFIX + "update.failed";
+    String ARTIFACT_NOT_FOUND = REPOSITORY_PREFIX + "artifact.notfound";
+    String REPOSITORY_LAYOUT_ERROR = REPOSITORY_PREFIX + "layout.error";
+
+    String ARTIFACT_COPY_ERROR = REPOSITORY_PREFIX + "artifact.copy.error";
+
+    /**
+     * The given user was not found
+     * Parameters:
+     * - User Id
+     */
+    String USER_NOT_FOUND = PREFIX+"user.not_found";
+
+    /**
+     * Error from UserManager
+     * Parameters:
+     * - Error Message
+     */
+    String USER_MANAGER_ERROR = PREFIX+"user_manager.error";
+
+    /**
+     * Permission to the repository denied.
+     * Parameters:
+     * - Repository Id
+     * - Permission ID
+     */
+    String PERMISSION_REPOSITORY_DENIED = PREFIX + "permission.repository.denied";
+
+    /**
+     * A generic authorization error thrown during the authorization check.
+     * Parameters:
+     * - Error message
+     */
+    String AUTHORIZATION_ERROR = PREFIX + "authorization.error";
+
+    /**
+     * When the operation needs authentication, but not authenticated user was found in the request context.
+     */
+    String NOT_AUTHENTICATED = PREFIX + "user.not_authenticated";
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorMessage.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorMessage.java
new file mode 100644 (file)
index 0000000..f3deebe
--- /dev/null
@@ -0,0 +1,102 @@
+package org.apache.archiva.rest.api.v2.svc;
+/*
+ * 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.swagger.v3.oas.annotations.media.Schema;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+
+/**
+ * @author Olivier Lamy
+ * @author Martin Stockhammer
+ * @since 3.0
+ */
+@XmlRootElement( name = "errorMessage" )
+@Schema(name="ErrorMessage",description = "Information about the error, that occurred while processing the REST request.")
+public class ErrorMessage
+    implements Serializable
+{
+    private String errorKey = "";
+
+    private String[] args = EMPTY;
+
+    private String message = "";
+
+    private static final String[] EMPTY = new String[0];
+
+    public ErrorMessage()
+    {
+        // no op
+    }
+
+    public ErrorMessage( String errorKey )
+    {
+        this.errorKey = errorKey;
+        this.args = EMPTY;
+    }
+
+    public ErrorMessage( String errorKey, String[] args )
+    {
+        this.errorKey = errorKey;
+        this.args = args;
+    }
+
+    public static ErrorMessage of(String errorKey, String... args) {
+        return new ErrorMessage( errorKey, args );
+    }
+
+    @Schema(name="error_key", description = "The key of the error message. If this is empty, the message message must be set.")
+    public String getErrorKey()
+    {
+        return errorKey;
+    }
+
+    public void setErrorKey( String errorKey )
+    {
+        this.errorKey = errorKey;
+    }
+
+    @Schema(description = "Parameters that can be filled to the translated error message")
+    public String[] getArgs()
+    {
+        return args;
+    }
+
+    public void setArgs( String[] args )
+    {
+        this.args = args;
+    }
+
+    @Schema(description = "Full error message. Either additional to the key in the default language, or if the message is without key.")
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public void setMessage( String message )
+    {
+        this.message = message;
+    }
+
+    public ErrorMessage message( String message )
+    {
+        this.message = message;
+        return this;
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryGroupService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryGroupService.java
new file mode 100644 (file)
index 0000000..aee7ac3
--- /dev/null
@@ -0,0 +1,256 @@
+package org.apache.archiva.rest.api.v2.svc;
+/*
+ * 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.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.headers.Header;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.parameters.RequestBody;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import org.apache.archiva.components.rest.model.PagedResult;
+import org.apache.archiva.redback.authorization.RedbackAuthorization;
+import org.apache.archiva.rest.api.v2.model.RepositoryGroup;
+import org.apache.archiva.security.common.ArchivaRoleConstants;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.apache.archiva.rest.api.v2.svc.RestConfiguration.DEFAULT_PAGE_LIMIT;
+
+/**
+ * Endpoint for repository groups that combine multiple repositories into a single virtual repository.
+ *
+ * @author Olivier Lamy
+ * @author Martin Stockhammer
+ * @since 3.0
+ */
+@Path( "/repository_groups" )
+@Schema( name = "RepositoryGroups", description = "Managing of repository groups or virtual repositories" )
+public interface RepositoryGroupService
+{
+    @Path( "" )
+    @GET
+    @Produces( {APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Returns all repository group entries.",
+        parameters = {
+            @Parameter( name = "q", description = "Search term" ),
+            @Parameter( name = "offset", description = "The offset of the first element returned" ),
+            @Parameter( name = "limit", description = "Maximum number of items to return in the response" ),
+            @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ),
+            @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" )
+        },
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the list could be returned",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    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( "id" ) List<String> orderBy,
+                                                        @QueryParam( "order" ) @DefaultValue( "asc" ) String order )
+        throws ArchivaRestServiceException;
+
+    @Path( "{id}" )
+    @GET
+    @Produces( {APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Returns a single repository group configuration.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the configuration is returned",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The repository group with the given id does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    RepositoryGroup getRepositoryGroup( @PathParam( "id" ) String repositoryGroupId )
+        throws ArchivaRestServiceException;
+
+    @Path( "" )
+    @POST
+    @Consumes( {APPLICATION_JSON} )
+    @Produces( {APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Creates a new group entry.",
+        requestBody =
+        @RequestBody( required = true, description = "The configuration of the repository group.",
+            content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) )
+        )
+        ,
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "201",
+                description = "If the repository group was created",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) )
+            ),
+            @ApiResponse( responseCode = "303", description = "The repository group exists already",
+                headers = {
+                    @Header( name = "Location", description = "The URL of existing group", schema = @Schema( type = "string" ) )
+                }
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "422", description = "The body data is not valid",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    RepositoryGroup addRepositoryGroup( RepositoryGroup repositoryGroup )
+        throws ArchivaRestServiceException;
+
+    @Path( "{id}" )
+    @PUT
+    @Consumes( {APPLICATION_JSON} )
+    @Produces( {APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Returns all repository group entries.",
+        requestBody =
+        @RequestBody( required = true, description = "The configuration of the repository group.",
+            content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) )
+        )
+        ,
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the group is returned",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The group with the given id does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "422", description = "The body data is not valid",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    RepositoryGroup updateRepositoryGroup( @PathParam( "id" ) String groupId, RepositoryGroup repositoryGroup )
+        throws ArchivaRestServiceException;
+
+    @Path( "{id}" )
+    @DELETE
+    @Produces( {APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Deletes the repository group entry with the given id.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the group was deleted"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The group with the given id does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+        }
+    )
+    Response deleteRepositoryGroup( @PathParam( "id" ) String repositoryGroupId )
+        throws ArchivaRestServiceException;
+
+    @Path( "{id}/repositories/{repositoryId}" )
+    @PUT
+    @Produces( {APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Adds the repository with the given id to the repository group.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the repository was added or if it was already part of the group"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The group with the given id does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+        }
+    )
+    RepositoryGroup addRepositoryToGroup( @PathParam( "id" ) String repositoryGroupId,
+                                          @PathParam( "repositoryId" ) String repositoryId )
+        throws ArchivaRestServiceException;
+
+    @Path( "{id}/repositories/{repositoryId}" )
+    @DELETE
+    @Produces( {APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Removes the repository with the given id from the repository group.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the repository was removed."
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "Either the group with the given id does not exist, or the repository was not part of the group.",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+        }
+    )
+    RepositoryGroup deleteRepositoryFromGroup( @PathParam( "id" ) String repositoryGroupId,
+                                               @PathParam( "repositoryId" ) String repositoryId )
+        throws ArchivaRestServiceException;
+
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryService.java
new file mode 100644 (file)
index 0000000..cdecbae
--- /dev/null
@@ -0,0 +1,272 @@
+package org.apache.archiva.rest.api.v2.svc;
+/*
+ * 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.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.apache.archiva.components.rest.model.PagedResult;
+import org.apache.archiva.redback.authorization.RedbackAuthorization;
+import org.apache.archiva.rest.api.v2.model.Repository;
+import org.apache.archiva.rest.api.v2.model.RepositoryStatistics;
+import org.apache.archiva.rest.api.v2.model.ScanStatus;
+import org.apache.archiva.security.common.ArchivaRoleConstants;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.List;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.apache.archiva.rest.api.v2.svc.RestConfiguration.DEFAULT_PAGE_LIMIT;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+@Path( "repositories" )
+@Tag(name = "v2")
+@Tag(name = "v2/Repositories")
+@Schema(name="RepositoryService",description = "Manage repositories of all types")
+public interface RepositoryService
+{
+
+    @Path( "" )
+    @GET
+    @Produces( {APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Returns all managed repositories.",
+        parameters = {
+            @Parameter( name = "q", description = "Search term" ),
+            @Parameter( name = "offset", description = "The offset of the first element returned" ),
+            @Parameter( name = "limit", description = "Maximum number of items to return in the response" ),
+            @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ),
+            @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" ),
+            @Parameter( name = "locale", description = "The locale for name and description" )
+        },
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the list could be returned",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    PagedResult<Repository> getRepositories( @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm,
+                                             @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset,
+                                             @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit,
+                                             @QueryParam( "orderBy" ) @DefaultValue( "id" ) List<String> orderBy,
+                                             @QueryParam( "order" ) @DefaultValue( "asc" ) String order,
+                                             @QueryParam( "locale" ) String localeString) throws ArchivaRestServiceException;
+
+    @Path( "managed/{id}/statistics" )
+    @GET
+    @Produces( {APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Returns repository statistic data.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the statistics could be returned",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryStatistics.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The repository does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    RepositoryStatistics getManagedRepositoryStatistics( @PathParam( "id" ) String repositoryId )
+        throws ArchivaRestServiceException;
+
+    @Path ("managed/{id}/scan/schedule")
+    @POST
+    @Produces ({ APPLICATION_JSON })
+    @Consumes({ APPLICATION_JSON })
+    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
+    @Operation( summary = "Returns repository statistic data.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the statistics could be returned"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The repository does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    Response scheduleRepositoryScan( @PathParam ("id") String repositoryId,
+                                     @QueryParam ("fullScan") boolean fullScan )
+        throws ArchivaRestServiceException;
+
+
+    @Path ("managed/{id}/scan/now")
+    @POST
+    @Produces ({ APPLICATION_JSON })
+    @Consumes({ APPLICATION_JSON })
+    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
+    @Operation( summary = "Runs a repository scan instantly and waits for the response.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the statistics could be returned",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryStatistics.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The repository does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    RepositoryStatistics scanRepositoryImmediately( @PathParam ("id") String repositoryId )
+        throws ArchivaRestServiceException;
+
+
+    @Path ("managed/{id}/scan/status")
+    @GET
+    @Produces ({ APPLICATION_JSON })
+    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
+    @Operation( summary = "Returns status of running and scheduled scans.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the status could be returned",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ScanStatus.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The repository does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    ScanStatus getScanStatus( @PathParam ("id") String repositoryId )
+        throws ArchivaRestServiceException;
+
+    @Path ("managed/{id}/scan")
+    @DELETE
+    @Produces ({ APPLICATION_JSON })
+    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
+    @Operation( summary = "Cancels and removes all tasks for the given repository.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the task was removed successfully"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The repository does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    Response removeScanningTaskFromQueue( @PathParam ("id") String repositoryId )
+        throws ArchivaRestServiceException;
+
+
+
+    @Path ("remote/{id}/index/download/start")
+    @POST
+    @Produces ({ APPLICATION_JSON })
+    @Consumes({ APPLICATION_JSON })
+    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
+    @Operation( summary = "Schedules a task for remote index download.",
+        parameters = {
+            @Parameter( name = "full", description = "If true, download the full index, otherwise try a update download." )
+        },
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the task was scheduled"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The repository does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    Response scheduleDownloadRemoteIndex( @PathParam ("id") String repositoryId,
+                                              @QueryParam( "immediate" ) boolean immediately,
+                                              @QueryParam ("full") boolean full, @Context UriInfo uriInfo )
+        throws ArchivaRestServiceException;
+
+
+    @Path ("remote/index/downloads")
+    @GET
+    @Produces ({ APPLICATION_JSON })
+    @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
+    @Operation( summary = "Returns a list of running downloads from the remote repository.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the artifact was deleted"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    List<String> getRunningRemoteDownloads();
+
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RestConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RestConfiguration.java
new file mode 100644 (file)
index 0000000..a363ddb
--- /dev/null
@@ -0,0 +1,43 @@
+package org.apache.archiva.rest.api.v2.svc;/*
+ * 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.
+ */
+
+/*
+ * 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.
+ */
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public interface RestConfiguration
+{
+    String DEFAULT_PAGE_LIMIT = "10";
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/SecurityConfigurationService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/SecurityConfigurationService.java
new file mode 100644 (file)
index 0000000..2db5243
--- /dev/null
@@ -0,0 +1,353 @@
+package org.apache.archiva.rest.api.v2.svc;
+/*
+ * 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.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.apache.archiva.components.rest.model.PagedResult;
+import org.apache.archiva.components.rest.model.PropertyEntry;
+import org.apache.archiva.redback.authorization.RedbackAuthorization;
+import org.apache.archiva.rest.api.v2.model.BeanInformation;
+import org.apache.archiva.rest.api.v2.model.CacheConfiguration;
+import org.apache.archiva.rest.api.v2.model.LdapConfiguration;
+import org.apache.archiva.rest.api.v2.model.SecurityConfiguration;
+import org.apache.archiva.security.common.ArchivaRoleConstants;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.apache.archiva.rest.api.v2.svc.RestConfiguration.DEFAULT_PAGE_LIMIT;
+
+/**
+ *
+ * Service for configuration of redback and security related settings.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+@Path( "/security" )
+@Tag(name = "v2")
+@Tag(name = "v2/Security")
+@SecurityRequirement(name = "BearerAuth")
+public interface SecurityConfigurationService
+{
+    @Path("config")
+    @GET
+    @Produces({ APPLICATION_JSON })
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Returns the security configuration that is currently active.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the configuration could be retrieved",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = SecurityConfiguration.class))
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    SecurityConfiguration getConfiguration()
+        throws ArchivaRestServiceException;
+
+    @Path("config")
+    @PUT
+    @Consumes({ APPLICATION_JSON })
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Updates the security configuration.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the configuration was updated"
+            ),
+            @ApiResponse( responseCode = "422", description = "Invalid content data",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the configuration",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    SecurityConfiguration updateConfiguration( SecurityConfiguration newConfiguration)
+        throws ArchivaRestServiceException;
+
+
+    @Path( "config/properties" )
+    @GET
+    @Produces( { APPLICATION_JSON } )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Returns all configuration properties. The result is paged.",
+        parameters = {
+            @Parameter(name = "q", description = "Search term"),
+            @Parameter(name = "offset", description = "The offset of the first element returned"),
+            @Parameter(name = "limit", description = "Maximum number of items to return in the response"),
+            @Parameter(name = "orderBy", description = "List of attribute used for sorting (key, value)"),
+            @Parameter(name = "order", description = "The sort order. Either ascending (asc) or descending (desc)")
+        },
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the list could be returned",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PagedResult.class))
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    PagedResult<PropertyEntry> getConfigurationProperties( @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("order") @DefaultValue( "asc" ) String order ) throws ArchivaRestServiceException;
+
+    @Path("config/properties/{propertyName}")
+    @GET
+    @Produces({ APPLICATION_JSON })
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Returns a single configuration property value.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        parameters = {
+            @Parameter(in = ParameterIn.PATH, name="propertyName", description = "The name of the property to get the value for")
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the configuration could be retrieved",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PropertyEntry.class))
+            ),
+            @ApiResponse( responseCode = "404", description = "The given property name does not exist",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    PropertyEntry getConfigurationProperty( @PathParam ( "propertyName" )  String propertyName)
+        throws ArchivaRestServiceException;
+
+
+    @Path("config/properties/{propertyName}")
+    @PUT
+    @Consumes({ APPLICATION_JSON})
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Updates a single property value of the security configuration.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        parameters = {
+            @Parameter(in = ParameterIn.PATH, name="propertyName", description = "The name of the property to update")
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the property value was updated."
+            ),
+            @ApiResponse( responseCode = "400", description = "The body data is not valid",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ),
+            @ApiResponse( responseCode = "404", description = "The given property name does not exist",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    Response updateConfigurationProperty( @PathParam ( "propertyName" )  String propertyName, PropertyEntry propertyValue)
+        throws ArchivaRestServiceException;
+
+    @Path("config/ldap")
+    @GET
+    @Produces({ APPLICATION_JSON })
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Returns the LDAP configuration that is currently active.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the configuration could be retrieved",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = LdapConfiguration.class))
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    LdapConfiguration getLdapConfiguration( ) throws ArchivaRestServiceException;
+
+    @Path("config/ldap")
+    @PUT
+    @Consumes({ APPLICATION_JSON })
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Updates the LDAP configuration that is currently active.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the configuration was updated"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    LdapConfiguration updateLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException;
+
+    @Path("config/ldap/verify")
+    @POST
+    @Consumes({ APPLICATION_JSON })
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Checks the given LDAP configuration.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the check was successful"
+            ),
+            @ApiResponse( responseCode = "400",
+                description = "If the check was not successful",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class ))
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    Response verifyLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException;
+
+    @Path("config/cache")
+    @GET
+    @Produces({ APPLICATION_JSON })
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Returns the cache configuration that is currently active.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the configuration could be retrieved",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = CacheConfiguration.class))
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    CacheConfiguration getCacheConfiguration( ) throws ArchivaRestServiceException;
+
+    @Path("config/cache")
+    @PUT
+    @Consumes({ APPLICATION_JSON })
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Updates the LDAP configuration that is currently active.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the configuration was updated"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    CacheConfiguration updateCacheConfiguration( CacheConfiguration cacheConfiguration ) throws ArchivaRestServiceException;
+
+
+    @Path("user_managers")
+    @GET
+    @Produces({ APPLICATION_JSON })
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Returns the available user manager implementations.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the list could be retrieved",
+                content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema(
+                    schema = @Schema(implementation = BeanInformation.class)))
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    List<BeanInformation> getAvailableUserManagers()
+        throws ArchivaRestServiceException;
+
+    @Path("rbac_managers")
+    @GET
+    @Produces({ APPLICATION_JSON })
+    @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION)
+    @Operation( summary = "Returns the available RBAC manager implementations.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the list could be retrieved",
+                content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema(
+                    schema = @Schema(implementation = BeanInformation.class)))
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) )
+        }
+    )
+    List<BeanInformation> getAvailableRbacManagers()
+        throws ArchivaRestServiceException;
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ValidationException.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ValidationException.java
new file mode 100644 (file)
index 0000000..c6ca653
--- /dev/null
@@ -0,0 +1,102 @@
+package org.apache.archiva.rest.api.v2.svc;
+/*
+ * 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.repository.Repository;
+import org.apache.archiva.repository.validation.ValidationResponse;
+import org.apache.archiva.rest.api.v2.model.ValidationError;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Exception is thrown
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class ValidationException extends ArchivaRestServiceException
+{
+    public static final int DEFAULT_CODE = 422;
+
+    public static final ErrorMessage DEFAULT_MESSAGE = new ErrorMessage( ErrorKeys.VALIDATION_ERROR );
+
+    private List<ValidationError> validationErrors;
+
+    public ValidationException( )
+    {
+        super( DEFAULT_MESSAGE, DEFAULT_CODE );
+    }
+
+    public ValidationException( int errorCode )
+    {
+        super( DEFAULT_MESSAGE, errorCode );
+    }
+
+    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 )
+    {
+        return new ValidationException( errorList.stream( ).map( ValidationError::of ).collect( Collectors.toList( ) ) );
+    }
+
+    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
+        {
+            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;
+    }
+
+    public void setValidationErrors( List<ValidationError> validationErrors )
+    {
+        this.validationErrors = validationErrors;
+    }
+
+    public void addValidationError( ValidationError error )
+    {
+        if ( this.validationErrors == null )
+        {
+            this.validationErrors = new ArrayList<>( );
+        }
+        this.validationErrors.add( error );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/maven/MavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/maven/MavenManagedRepositoryService.java
new file mode 100644 (file)
index 0000000..404d913
--- /dev/null
@@ -0,0 +1,369 @@
+package org.apache.archiva.rest.api.v2.svc.maven;
+/*
+ * 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.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.headers.Header;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.apache.archiva.components.rest.model.PagedResult;
+import org.apache.archiva.redback.authorization.RedbackAuthorization;
+import org.apache.archiva.rest.api.v2.model.FileInfo;
+import org.apache.archiva.rest.api.v2.model.MavenManagedRepository;
+import org.apache.archiva.rest.api.v2.model.MavenManagedRepositoryUpdate;
+import org.apache.archiva.rest.api.v2.svc.ArchivaRestError;
+import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException;
+import org.apache.archiva.security.common.ArchivaRoleConstants;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.apache.archiva.rest.api.v2.svc.RestConfiguration.DEFAULT_PAGE_LIMIT;
+
+/**
+ * Service interface for managing managed maven repositories
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+@Schema( name = "ManagedRepositoryService", description = "Managing and configuration of managed repositories" )
+@Path( "repositories/maven/managed" )
+@Tag(name = "v2")
+@Tag(name = "v2/Repositories")
+public interface MavenManagedRepositoryService
+{
+    @Path( "" )
+    @GET
+    @Produces( {APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Returns all managed repositories.",
+        parameters = {
+            @Parameter( name = "q", description = "Search term" ),
+            @Parameter( name = "offset", description = "The offset of the first element returned" ),
+            @Parameter( name = "limit", description = "Maximum number of items to return in the response" ),
+            @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ),
+            @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" )
+        },
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the list could be returned",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    PagedResult<MavenManagedRepository> getManagedRepositories(
+        @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm,
+        @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset,
+        @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit,
+        @QueryParam( "orderBy" ) @DefaultValue( "id" ) List<String> orderBy,
+        @QueryParam( "order" ) @DefaultValue( "asc" ) String order )
+        throws ArchivaRestServiceException;
+
+
+    @Path( "{id}" )
+    @GET
+    @Produces( {MediaType.APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Returns the managed repository with the given id.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the managed repository could be returned",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    MavenManagedRepository getManagedRepository( @PathParam( "id" ) String repositoryId )
+        throws ArchivaRestServiceException;
+
+
+    @Path( "{id}" )
+    @DELETE
+    @Produces( {MediaType.APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Deletes the managed repository with the given id.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the managed repository could be returned"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    Response deleteManagedRepository( @PathParam( "id" ) String repositoryId,
+                                      @QueryParam( "deleteContent" ) boolean deleteContent )
+        throws ArchivaRestServiceException;
+
+
+    @Path( "" )
+    @POST
+    @Consumes( {MediaType.APPLICATION_JSON} )
+    @Produces( {MediaType.APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Creates the managed repository",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "201",
+                description = "If the managed repository could be created",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) )
+            ),
+            @ApiResponse( responseCode = "303", description = "The repository exists already",
+                headers = {
+                    @Header( name = "Location", description = "The URL of existing repository ", schema = @Schema( type = "string" ) )
+                }
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "422", description = "The body data is not valid",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    MavenManagedRepository addManagedRepository( MavenManagedRepository managedRepository )
+        throws ArchivaRestServiceException;
+
+
+    @Path( "{id}" )
+    @PUT
+    @Consumes( {MediaType.APPLICATION_JSON} )
+    @Produces( {MediaType.APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+    @Operation( summary = "Updates the managed repository with the given id",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the managed repository could be updated",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "422", description = "The body data is not valid",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    MavenManagedRepository updateManagedRepository( @PathParam( "id" ) String repositoryId,  MavenManagedRepositoryUpdate managedRepository )
+        throws ArchivaRestServiceException;
+
+
+    @Path( "{id}/path/{filePath: .+}" )
+    @GET
+    @Produces( {MediaType.APPLICATION_JSON} )
+    @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, resource = "{id}")
+    @Operation( summary = "Returns the status of a given file in the repository",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the file status is returned",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = FileInfo.class ) )
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the file does not exist.",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    FileInfo getFileStatus( @PathParam( "id" ) String repositoryId, @PathParam( "filePath" ) String fileLocation )
+        throws ArchivaRestServiceException;
+
+
+    /**
+     * Permissions are checked in impl
+     * will copy an artifact from the source repository to the target repository
+     */
+    @Path ("{srcId}/path/{path: .+}/copyto/{dstId}")
+    @POST
+    @Produces({APPLICATION_JSON})
+    @RedbackAuthorization (noPermission = true)
+    @Operation( summary = "Copies a artifact from the source repository to the destination repository",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS,
+                scopes = {
+                    "{srcId}"
+                }
+            ),
+            @SecurityRequirement(
+                name= ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD,
+                scopes = {
+                    "{dstId}"
+                }
+            )
+
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the artifact was copied"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The repository does not exist, or if the artifact was not found",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    Response copyArtifact( @PathParam( "srcId" ) String srcRepositoryId, @PathParam( "dstId" ) String dstRepositoryId,
+                           @PathParam( "path" ) String path )
+        throws ArchivaRestServiceException;
+
+
+    @Path ("{id}/path/{path: .+}")
+    @DELETE
+    @Consumes ({ APPLICATION_JSON })
+    @RedbackAuthorization (noPermission = true)
+    @Operation( summary = "Deletes a artifact in the repository.",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the artifact was deleted"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The repository or the artifact does not exist",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    Response deleteArtifact( @PathParam( "id" ) String repositoryId, @PathParam( "path" ) String path )
+        throws ArchivaRestServiceException;
+
+    @Path ( "{id}/co/{group}/{project}/{version}" )
+    @DELETE
+    @Produces ({ MediaType.APPLICATION_JSON })
+    @RedbackAuthorization (noPermission = true)
+    @Operation( summary = "Removes a version tree in the repository",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the deletion was successful"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete in repositories",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the version does not exist.",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    Response removeProjectVersion( @PathParam ( "id" ) String repositoryId,
+                                   @PathParam ( "group" ) String namespace, @PathParam ( "project" ) String projectId,
+                                   @PathParam ( "version" ) String version )
+        throws org.apache.archiva.rest.api.services.ArchivaRestServiceException;
+
+
+    @Path ( "{id}/co/{group}/{project}" )
+    @DELETE
+    @Produces ({ MediaType.APPLICATION_JSON })
+    @RedbackAuthorization (noPermission = true)
+    @Operation( summary = "Removes a project tree in the repository",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the deletion was successful"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete in repositories",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the project does not exist.",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    Response deleteProject( @PathParam ("id") String repositoryId, @PathParam ( "group" ) String namespace, @PathParam ( "project" ) String projectId )
+        throws org.apache.archiva.rest.api.services.ArchivaRestServiceException;
+
+    @Path ( "{id}/co/{namespace}" )
+    @DELETE
+    @Produces ({ MediaType.APPLICATION_JSON })
+    @RedbackAuthorization (noPermission = true)
+    @Operation( summary = "Removes a namespace tree in the repository",
+        security = {
+            @SecurityRequirement(
+                name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION
+            )
+        },
+        responses = {
+            @ApiResponse( responseCode = "200",
+                description = "If the deletion was successful"
+            ),
+            @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete namespaces in repositories",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
+            @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the namespace does not exist.",
+                content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
+        }
+    )
+    Response deleteNamespace( @PathParam ("id") String repositoryId, @PathParam ( "namespace" ) String namespace )
+        throws org.apache.archiva.rest.api.services.ArchivaRestServiceException;
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/package-info.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/package-info.java
new file mode 100644 (file)
index 0000000..f4d0763
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+/**
+ * <p>This is the V2 REST API of Archiva. It uses JAX-RS annotations for defining the endpoints.
+ * The API is documented with OpenApi annotations.</p>
+ *
+ * <h3>Some design principles of the API and classes:</h3>
+ * <ul>
+ *     <li>All services use V2 model classes. Internal models are always converted to V2 classes.</li>
+ *     <li>Schema attributes use the snake case syntax (lower case with '_' as divider)</li>
+ *     <li>Return code <code>200</code> and <code>201</code> (POST) is used for successful execution.</li>
+ *     <li>Return code <code>403</code> is used, if the user has not the permission for the action.</li>
+ *     <li>Return code <code>422</code> is used for input that has invalid data.</li>
+ * </ul>
+ *
+ * <h4>Querying entity lists</h4>
+ * <p>The main entities of a given path are retrieved on the base path.
+ * Further sub entities or entries may be retrieved via subpaths.
+ * A single entity is returned by the "{id}" path. Be careful with technical paths that are parallel to the
+ * id path. Avoid naming conflicts with the id and technical paths.
+ * Entity attributes may be retrieved by "{id}/{attribute}" path or if there are lists or collections by
+ * "{id}/mycollection/{subentryid}"</p>
+ *
+ * <ul>
+ *  <li><code>GET</code> method is used for retrieving entities on the base path ""</li>
+ *  <li>The query for base entities should always return a paged result and be filterable and sortable</li>
+ *  <li>Query parameters for filtering, ordering and limits should be optional and proper defaults must be set</li>
+ *  <li>Return code <code>200</code> is used for successful retrieval</li>
+ *  <li>This action is idempotent</li>
+ * </ul>
+ *
+ * <h4>Querying single entities</h4>
+ * <p>Single entities are retrieved on the path "{id}"</p>
+ * <ul>
+ *  <li><code>GET</code> method is used for retrieving a single entity. The id is always a path parameter.</li>
+ *  <li>Return code <code>200</code> is used for successful retrieval</li>
+ *  <li>Return code <code>404</code> is used if the entity with the given id does not exist</li>
+ *  <li>This action is idempotent</li>
+ * </ul>
+ *
+ * <h4>Creating entities</h4>
+ * <p>The main entities are created on the base path "".</p>
+ * <ul>
+ *     <li><code>POST</code> is used for creating new entities</li>
+ *     <li>The <code>POST</code> body must always have a complete definition of the entity.</li>
+ *     <li>A unique <code>id</code> or <code>name</code> attribute is required for entities. If the id is generated during POST,
+ *     it must be returned by response body.</li>
+ *     <li>A successful <code>POST</code> request should always return the entity definition as it would be returned by the GET request.</li>
+ *     <li>Return code <code>201</code> is used for successful creation of the new entity.</li>
+ *     <li>A successful response has a <code>Location</code> header with the URL for retrieving the single created entity.</li>
+ *     <li>Return code <code>303</code> is used, if the entity exists already</li>
+ *     <li>This action is not idempotent</li>
+ * </ul>
+ *
+ * <h4>Updating entities</h4>
+ * <p>The path for entity update must contain the '{id}' of the entity. The path should be the same as for the GET operation.</p>
+ * <ul>
+ *     <li><code>PUT</code> is used for updating existing entities</li>
+ *     <li>The body contains a JSON object. Only existing attributes are updated.</li>
+ *     <li>A successful PUT request should return the complete entity definition as it would be returned by the GET request.</li>
+ *     <li>Return code <code>200</code> is used for successful update of the new entity. Even if nothing changed.</li>
+ *     <li>This action is idempotent</li>
+ * </ul>
+ *
+ * <h4>Deleting entities</h4>
+ * <p>The path for entity deletion must contain the '{id}' of the entity. The path should be the same as
+ * for the GET operation.</p>
+ * <ul>
+ *     <li><code>DELETE</code> is used for deleting existing entities</li>
+ *     <li>The successful operation has no request and no response body</li>
+ *     <li>Return code <code>200</code> is used for successful deletion of the new entity.</li>
+ *     <li>This action is not idempotent</li>
+ * </ul>
+ *
+ * <h4>Errors</h4>
+ * <ul>
+ *     <li>A error uses a return code <code>>=400</code> </li>
+ *     <li>All errors use the same result object ({@link org.apache.archiva.rest.api.v2.svc.ArchivaRestError}</li>
+ *     <li>Error messages are returned as keys. Translation is part of the client application.</li>
+ * </ul>
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+package org.apache.archiva.rest.api.v2.svc;
\ No newline at end of file
index 7ddbdb92e057c449f8f08ad83839ec0712cef4ef..379f9dbd5d4708d1f730506bfd5ad7b9c643797c 100644 (file)
@@ -1,6 +1,6 @@
 resourcePackages:
-  - org.apache.archiva.rest.api.services.v2
-  - org.apache.archiva.rest.api.model.v2
+  - org.apache.archiva.rest.api.v2.svc
+  - org.apache.archiva.rest.api.v2.model
 
 prettyPrint: true
 cacheTTL: 0
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/interceptors/v2/ArchivaRestServiceExceptionMapper.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/interceptors/v2/ArchivaRestServiceExceptionMapper.java
deleted file mode 100644 (file)
index 1296374..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.apache.archiva.rest.services.interceptors.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 org.apache.archiva.rest.api.services.v2.ArchivaRestError;
-import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
-import org.springframework.stereotype.Service;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
-
-/**
- * Maps exceptions to REST responses.
- *
- * @author Martin Stockhammer
- * @since 3.0
- */
-@Provider
-@Service( "v2.archivaRestServiceExceptionMapper" )
-public class ArchivaRestServiceExceptionMapper
-    implements ExceptionMapper<ArchivaRestServiceException>
-{
-    @Override
-    public Response toResponse( final ArchivaRestServiceException e )
-    {
-        ArchivaRestError restError = new ArchivaRestError( e );
-
-        Response.ResponseBuilder responseBuilder = Response.status( e.getHttpErrorCode() ).entity( restError );
-        if ( e.getMessage() != null )
-        {
-            responseBuilder = responseBuilder.status( new Response.StatusType()
-            {
-                public int getStatusCode()
-                {
-                    return e.getHttpErrorCode();
-                }
-
-                public Response.Status.Family getFamily()
-                {
-                    return Response.Status.Family.familyOf( e.getHttpErrorCode( ) );
-                }
-
-                public String getReasonPhrase()
-                {
-                    return e.getMessage();
-                }
-            } );
-        }
-        return responseBuilder.build();
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java
deleted file mode 100644 (file)
index 7b776a7..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-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 org.apache.archiva.admin.model.AuditInformation;
-import org.apache.archiva.admin.model.RepositoryAdminException;
-import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
-import org.apache.archiva.components.rest.model.PagedResult;
-import org.apache.archiva.components.rest.util.QueryHelper;
-import org.apache.archiva.redback.authentication.AuthenticationResult;
-import org.apache.archiva.redback.authorization.AuthorizationException;
-import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal;
-import org.apache.archiva.redback.rest.services.RedbackRequestInformation;
-import org.apache.archiva.redback.system.DefaultSecuritySession;
-import org.apache.archiva.redback.system.SecuritySession;
-import org.apache.archiva.redback.system.SecuritySystem;
-import org.apache.archiva.redback.users.User;
-import org.apache.archiva.redback.users.UserManagerException;
-import org.apache.archiva.redback.users.UserNotFoundException;
-import org.apache.archiva.repository.ManagedRepository;
-import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.Repository;
-import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.content.ContentItem;
-import org.apache.archiva.repository.content.LayoutException;
-import org.apache.archiva.repository.storage.fs.FsStorageUtil;
-import org.apache.archiva.rest.api.model.v2.FileInfo;
-import org.apache.archiva.rest.api.model.v2.MavenManagedRepository;
-import org.apache.archiva.rest.api.model.v2.MavenManagedRepositoryUpdate;
-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.maven.MavenManagedRepositoryService;
-import org.apache.archiva.security.common.ArchivaRoleConstants;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.List;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS;
-import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Service("v2.managedMavenRepositoryService#rest")
-public class DefaultMavenManagedRepositoryService implements MavenManagedRepositoryService
-{
-    @Context
-    HttpServletResponse httpServletResponse;
-
-    @Context
-    UriInfo uriInfo;
-
-    private static final Logger log = LoggerFactory.getLogger( DefaultMavenManagedRepositoryService.class );
-    private static final QueryHelper<ManagedRepository> QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} );
-    static
-    {
-        QUERY_HELPER.addStringFilter( "id", ManagedRepository::getId );
-        QUERY_HELPER.addStringFilter( "name", ManagedRepository::getName );
-        QUERY_HELPER.addStringFilter( "location", (r)  -> r.getLocation().toString() );
-        QUERY_HELPER.addBooleanFilter( "snapshot", (r) -> r.getActiveReleaseSchemes( ).contains( ReleaseScheme.SNAPSHOT ) );
-        QUERY_HELPER.addBooleanFilter( "release", (r) -> r.getActiveReleaseSchemes().contains( ReleaseScheme.RELEASE ));
-        QUERY_HELPER.addNullsafeFieldComparator( "id", ManagedRepository::getId );
-        QUERY_HELPER.addNullsafeFieldComparator( "name", ManagedRepository::getName );
-    }
-
-    private ManagedRepositoryAdmin managedRepositoryAdmin;
-    private RepositoryRegistry repositoryRegistry;
-    private SecuritySystem securitySystem;
-
-    public DefaultMavenManagedRepositoryService( SecuritySystem securitySystem,
-                                                 RepositoryRegistry repositoryRegistry,
-                                                 ManagedRepositoryAdmin managedRepositoryAdmin )
-    {
-        this.securitySystem = securitySystem;
-        this.repositoryRegistry = repositoryRegistry;
-        this.managedRepositoryAdmin = managedRepositoryAdmin;
-    }
-
-    protected AuditInformation getAuditInformation( )
-    {
-        RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get( );
-        User user;
-        String remoteAddr;
-        if (redbackRequestInformation==null) {
-            user = null;
-            remoteAddr = null;
-        } else
-        {
-            user = redbackRequestInformation.getUser( );
-            remoteAddr = redbackRequestInformation.getRemoteAddr( );
-        }
-        return new AuditInformation( user, remoteAddr );
-    }
-
-    @Override
-    public PagedResult<MavenManagedRepository> getManagedRepositories( final String searchTerm, final Integer offset,
-                                                                       final Integer limit, final List<String> orderBy,
-                                                                       final String order ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            Collection<ManagedRepository> repos = repositoryRegistry.getManagedRepositories( );
-            final Predicate<ManagedRepository> queryFilter = QUERY_HELPER.getQueryFilter( searchTerm ).and( r -> r.getType() == RepositoryType.MAVEN );
-            final Comparator<ManagedRepository> comparator = QUERY_HELPER.getComparator( orderBy, order );
-            int totalCount = Math.toIntExact( repos.stream( ).filter( queryFilter ).count( ) );
-            return PagedResult.of( totalCount, offset, limit, repos.stream( ).filter( queryFilter ).sorted( comparator )
-                .map(mr -> MavenManagedRepository.of(mr)).skip( offset ).limit( limit ).collect( Collectors.toList( ) ) );
-        }
-        catch (ArithmeticException e) {
-            log.error( "Invalid number of repositories detected." );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) );
-        }
-    }
-
-    @Override
-    public MavenManagedRepository getManagedRepository( String repositoryId ) throws ArchivaRestServiceException
-    {
-        ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId );
-        if (repo==null) {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
-        }
-        if (repo.getType()!=RepositoryType.MAVEN) {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 );
-        }
-        return MavenManagedRepository.of( repo );
-    }
-
-    @Override
-    public Response deleteManagedRepository( String repositoryId, boolean deleteContent ) throws ArchivaRestServiceException
-    {
-        ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId );
-        if (repo==null) {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
-        }
-        if (repo.getType()!=RepositoryType.MAVEN) {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 );
-        }
-        try
-        {
-            managedRepositoryAdmin.deleteManagedRepository( repositoryId, getAuditInformation( ), deleteContent );
-            return Response.ok( ).build( );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_DELETE_FAILED, e.getMessage( ) ) );
-        }
-    }
-
-    private org.apache.archiva.admin.model.beans.ManagedRepository convert(MavenManagedRepository repository) {
-        org.apache.archiva.admin.model.beans.ManagedRepository repoBean = new org.apache.archiva.admin.model.beans.ManagedRepository( );
-        repoBean.setId( repository.getId( ) );
-        repoBean.setName( repository.getName() );
-        repoBean.setDescription( repository.getDescription() );
-        repoBean.setBlockRedeployments( repository.isBlocksRedeployments() );
-        repoBean.setCronExpression( repository.getSchedulingDefinition() );
-        repoBean.setLocation( repository.getLocation() );
-        repoBean.setReleases( repository.getReleaseSchemes().contains( ReleaseScheme.RELEASE.name() ) );
-        repoBean.setSnapshots( repository.getReleaseSchemes().contains( ReleaseScheme.SNAPSHOT.name() ) );
-        repoBean.setScanned( repository.isScanned() );
-        repoBean.setDeleteReleasedSnapshots( repository.isDeleteSnapshotsOfRelease() );
-        repoBean.setSkipPackedIndexCreation( repository.isSkipPackedIndexCreation() );
-        repoBean.setRetentionCount( repository.getRetentionCount() );
-        repoBean.setRetentionPeriod( repository.getRetentionPeriod().getDays() );
-        repoBean.setIndexDirectory( repository.getIndexPath() );
-        repoBean.setPackedIndexDirectory( repository.getPackedIndexPath() );
-        repoBean.setLayout( repository.getLayout() );
-        repoBean.setType( RepositoryType.MAVEN.name( ) );
-        return repoBean;
-    }
-
-    @Override
-    public MavenManagedRepository addManagedRepository( MavenManagedRepository managedRepository ) throws ArchivaRestServiceException
-    {
-        final String repoId = managedRepository.getId( );
-        if ( StringUtils.isEmpty( repoId ) ) {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_INVALID_ID, repoId ), 422 );
-        }
-        Repository repo = repositoryRegistry.getRepository( repoId );
-        if (repo!=null) {
-            httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( repoId ).build( ).toString( ) );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ID_EXISTS, repoId ), 303 );
-        }
-        try
-        {
-            managedRepositoryAdmin.addManagedRepository( convert( managedRepository ), managedRepository.isHasStagingRepository(), getAuditInformation() );
-            httpServletResponse.setStatus( 201 );
-            return MavenManagedRepository.of( repositoryRegistry.getManagedRepository( repoId ) );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
-        }
-    }
-
-    @Override
-    public MavenManagedRepository updateManagedRepository( final String repositoryId, final MavenManagedRepositoryUpdate managedRepository ) throws ArchivaRestServiceException
-    {
-        org.apache.archiva.admin.model.beans.ManagedRepository repo = convert( managedRepository );
-        try
-        {
-            managedRepositoryAdmin.updateManagedRepository( repo, managedRepository.isHasStagingRepository( ), getAuditInformation( ), managedRepository.isResetStats( ) );
-            ManagedRepository newRepo = repositoryRegistry.getManagedRepository( managedRepository.getId( ) );
-            if (newRepo==null) {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_UPDATE_FAILED, repositoryId ) );
-            }
-            return MavenManagedRepository.of( newRepo );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
-        }
-    }
-
-    @Override
-    public FileInfo getFileStatus( String repositoryId, String fileLocation ) throws ArchivaRestServiceException
-    {
-        ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId );
-        if (repo==null) {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
-        }
-        try
-        {
-            ContentItem contentItem = repo.getContent( ).toItem( fileLocation );
-            if (contentItem.getAsset( ).exists( ))  {
-                return FileInfo.of( contentItem.getAsset( ) );
-            } else {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_NOT_FOUND, repositoryId, fileLocation ), 404 );
-            }
-        }
-        catch ( LayoutException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_LAYOUT_ERROR, e.getMessage( ) ) );
-        }
-    }
-
-    @Override
-    public Response copyArtifact( String srcRepositoryId, String dstRepositoryId,
-                                  String path ) throws ArchivaRestServiceException
-    {
-        final AuditInformation auditInformation = getAuditInformation( );
-        final String userName = auditInformation.getUser( ).getUsername( );
-        if ( StringUtils.isEmpty( userName ) )
-        {
-            httpServletResponse.setHeader( "WWW-Authenticate", "Bearer realm=\"archiva\"" );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.NOT_AUTHENTICATED ), 401 );
-        }
-        ManagedRepository srcRepo = repositoryRegistry.getManagedRepository( srcRepositoryId );
-        if (srcRepo==null) {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, srcRepositoryId ), 404 );
-        }
-        ManagedRepository dstRepo = repositoryRegistry.getManagedRepository( dstRepositoryId );
-        if (dstRepo==null) {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, dstRepositoryId ), 404 );
-        }
-        checkAuthority( auditInformation.getUser().getUsername(), srcRepositoryId, dstRepositoryId );
-        try
-        {
-            ContentItem srcItem = srcRepo.getContent( ).toItem( path );
-            ContentItem dstItem = dstRepo.getContent( ).toItem( path );
-            if (!srcItem.getAsset().exists()){
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_NOT_FOUND, srcRepositoryId, path ), 404 );
-            }
-            if (dstItem.getAsset().exists()) {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_EXISTS_AT_DEST, srcRepositoryId, path ), 400 );
-            }
-            FsStorageUtil.copyAsset( srcItem.getAsset( ), dstItem.getAsset( ), true );
-        }
-        catch ( LayoutException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_LAYOUT_ERROR, e.getMessage() ) );
-        }
-        catch ( IOException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_COPY_ERROR, e.getMessage() ) );
-        }
-        return Response.ok( ).build();
-    }
-
-    private void checkAuthority(final String userName, final String srcRepositoryId, final String dstRepositoryId ) throws ArchivaRestServiceException {
-        User user = null;
-        try
-        {
-            user = securitySystem.getUserManager().findUser( userName );
-        }
-        catch ( UserNotFoundException e )
-        {
-            httpServletResponse.setHeader( "WWW-Authenticate", "Bearer realm=\"archiva\"" );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.USER_NOT_FOUND, userName ), 401 );
-        }
-        catch ( UserManagerException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.USER_MANAGER_ERROR, e.getMessage( ) ) );
-        }
-
-        // check karma on source : read
-        AuthenticationResult authn = new AuthenticationResult( true, userName, null );
-        SecuritySession securitySession = new DefaultSecuritySession( authn, user );
-        try
-        {
-            boolean authz =
-                securitySystem.isAuthorized( securitySession, OPERATION_REPOSITORY_ACCESS,
-                    srcRepositoryId );
-            if ( !authz )
-            {
-                throw new ArchivaRestServiceException(ErrorMessage.of( ErrorKeys.PERMISSION_REPOSITORY_DENIED, srcRepositoryId, OPERATION_REPOSITORY_ACCESS ), 403);
-            }
-        }
-        catch ( AuthorizationException e )
-        {
-            log.error( "Error reading permission: {}", e.getMessage(), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.AUTHORIZATION_ERROR, e.getMessage() ), 403);
-        }
-
-        // check karma on target: write
-        try
-        {
-            boolean authz =
-                securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD,
-                    dstRepositoryId );
-            if ( !authz )
-            {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PERMISSION_REPOSITORY_DENIED, dstRepositoryId, OPERATION_REPOSITORY_UPLOAD ) );
-            }
-        }
-        catch ( AuthorizationException e )
-        {
-            log.error( "Error reading permission: {}", e.getMessage(), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.AUTHORIZATION_ERROR, e.getMessage() ), 403);
-        }
-
-
-    }
-
-    @Override
-    public Response deleteArtifact( String repositoryId, String path ) throws ArchivaRestServiceException
-    {
-
-        return null;
-    }
-
-
-    @Override
-    public Response removeProjectVersion( String repositoryId, String namespace, String projectId, String version ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException
-    {
-        return null;
-    }
-
-    @Override
-    public Response deleteProject( String repositoryId, String namespace, String projectId ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException
-    {
-        return null;
-    }
-
-    @Override
-    public Response deleteNamespace( String repositoryId, String namespace ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException
-    {
-        return null;
-    }
-
-}
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
deleted file mode 100644 (file)
index 9ecd914..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-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.
- */
-
-/*
- * 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.components.rest.model.PagedResult;
-import org.apache.archiva.components.rest.util.QueryHelper;
-import org.apache.archiva.configuration.RepositoryGroupConfiguration;
-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.CheckedResult;
-import org.apache.archiva.repository.validation.ValidationError;
-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 org.apache.archiva.rest.api.services.v2.ErrorMessage;
-import org.apache.archiva.rest.api.services.v2.RepositoryGroupService;
-import org.apache.archiva.rest.api.services.v2.ValidationException;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Response;
-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;
-
-/**
- * REST V2 Implementation for repository groups.
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- * @see RepositoryGroupService
- * @since 3.0
- */
-@Service( "v2.repositoryGroupService#rest" )
-public class DefaultRepositoryGroupService implements RepositoryGroupService
-{
-    private final ConfigurationHandler configurationHandler;
-
-    @Context
-    HttpServletResponse httpServletResponse;
-
-    @Context
-    UriInfo uriInfo;
-
-    final private RepositoryRegistry repositoryRegistry;
-
-
-    private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryGroupService.class );
-    private static final QueryHelper<org.apache.archiva.repository.RepositoryGroup> QUERY_HELPER = new QueryHelper<>( new String[]{"id"} );
-
-    static
-    {
-        QUERY_HELPER.addStringFilter( "id", org.apache.archiva.repository.RepositoryGroup::getId );
-        QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.repository.RepositoryGroup::getId );
-    }
-
-
-    public DefaultRepositoryGroupService( RepositoryRegistry repositoryRegistry, ConfigurationHandler configurationHandler )
-    {
-        this.repositoryRegistry = repositoryRegistry;
-        this.configurationHandler = configurationHandler;
-    }
-
-    @Override
-    public PagedResult<RepositoryGroup> getRepositoriesGroups( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            Predicate<org.apache.archiva.repository.RepositoryGroup> filter = QUERY_HELPER.getQueryFilter( searchTerm );
-            Comparator<org.apache.archiva.repository.RepositoryGroup> ordering = QUERY_HELPER.getComparator( orderBy, QUERY_HELPER.isAscending( order ) );
-            int totalCount = Math.toIntExact( repositoryRegistry.getRepositoryGroups( ).stream( ).filter( filter ).count( ) );
-            List<RepositoryGroup> result = repositoryRegistry.getRepositoryGroups( ).stream( ).filter( filter ).sorted( ordering ).skip( offset ).limit( limit ).map(
-                RepositoryGroup::of
-            ).collect( Collectors.toList( ) );
-            return new PagedResult<>( totalCount, offset, limit, result );
-        }
-        catch ( ArithmeticException e )
-        {
-            log.error( "Could not convert total count: {}", e.getMessage( ) );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) );
-        }
-
-    }
-
-    @Override
-    public RepositoryGroup getRepositoryGroup( String repositoryGroupId ) throws ArchivaRestServiceException
-    {
-        if ( StringUtils.isEmpty( repositoryGroupId ) )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
-        }
-        org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
-        return RepositoryGroup.of( group );
-    }
-
-    private RepositoryGroupConfiguration toConfig( RepositoryGroup group )
-    {
-        RepositoryGroupConfiguration result = new RepositoryGroupConfiguration( );
-        result.setId( group.getId( ) );
-        result.setName( group.getName() );
-        result.setLocation( group.getLocation( ) );
-        result.setRepositories( group.getRepositories( ) );
-        MergeConfiguration mergeConfig = group.getMergeConfiguration( );
-        if ( mergeConfig != null )
-        {
-            result.setMergedIndexPath( mergeConfig.getMergedIndexPath( ) );
-            result.setMergedIndexTtl( mergeConfig.getMergedIndexTtlMinutes( ) );
-            result.setCronExpression( mergeConfig.getIndexMergeSchedule( ) );
-        }
-        return result;
-    }
-
-    @Override
-    public RepositoryGroup addRepositoryGroup( RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException
-    {
-        final String groupId = repositoryGroup.getId( );
-        if ( StringUtils.isEmpty( groupId ) )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_INVALID_ID, groupId ), 422 );
-        }
-        if ( repositoryRegistry.hasRepositoryGroup( groupId ) )
-        {
-            httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( groupId ).build( ).toString( ) );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ID_EXISTS, groupId ), 303 );
-        }
-        try
-        {
-
-            RepositoryGroupConfiguration configuration = toConfig( repositoryGroup );
-            CheckedResult<org.apache.archiva.repository.RepositoryGroup, Map<String, List<ValidationError>>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration );
-            if ( validationResult.isValid( ) )
-            {
-                httpServletResponse.setStatus( 201 );
-                return RepositoryGroup.of( validationResult.getRepository( ) );
-            }
-            else
-            {
-                throw ValidationException.of( validationResult.getResult( ) );
-            }
-        }
-        catch ( RepositoryException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_ADD_FAILED ) );
-        }
-    }
-
-    @Override
-    public RepositoryGroup updateRepositoryGroup( final String repositoryGroupId, final RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException
-    {
-        if ( StringUtils.isEmpty( repositoryGroupId ) )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
-        }
-        if ( !repositoryRegistry.hasRepositoryGroup( repositoryGroupId ) )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND ), 404 );
-        }
-        repositoryGroup.setId( repositoryGroupId );
-        try
-        {
-            RepositoryGroupConfiguration configuration = toConfig( repositoryGroup );
-            CheckedResult<org.apache.archiva.repository.RepositoryGroup, Map<String, List<ValidationError>>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration );
-            if ( validationResult.isValid( ) )
-            {
-                httpServletResponse.setStatus( 201 );
-                return RepositoryGroup.of( validationResult.getRepository( ) );
-            }
-            else
-            {
-                throw ValidationException.of( validationResult.getResult( ) );
-            }
-        }
-        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( ) ) );
-
-        }
-    }
-
-    @Override
-    public Response deleteRepositoryGroup( String repositoryGroupId ) throws ArchivaRestServiceException
-    {
-        if ( StringUtils.isEmpty( repositoryGroupId ) )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
-        }
-        try
-        {
-            org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
-            if ( group == null )
-            {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
-            }
-            repositoryRegistry.removeRepositoryGroup( group );
-            return Response.ok( ).build( );
-        }
-        catch ( RepositoryException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_DELETE_FAILED ) );
-        }
-    }
-
-    @Override
-    public RepositoryGroup addRepositoryToGroup( String repositoryGroupId, String repositoryId ) throws ArchivaRestServiceException
-    {
-        if ( StringUtils.isEmpty( repositoryGroupId ) )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
-        }
-        if ( StringUtils.isEmpty( repositoryId ) )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, "" ), 404 );
-        }
-        try
-        {
-            org.apache.archiva.repository.RepositoryGroup repositoryGroup = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
-            if ( repositoryGroup == null )
-            {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
-            }
-            if ( !( repositoryGroup instanceof EditableRepositoryGroup ) )
-            {
-                log.error( "This group instance is not editable: {}", repositoryGroupId );
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, "" ), 500 );
-            }
-            EditableRepositoryGroup editableRepositoryGroup = (EditableRepositoryGroup) repositoryGroup;
-            if ( editableRepositoryGroup.getRepositories( ).stream( ).anyMatch( repo -> repositoryId.equals( repo.getId( ) ) ) )
-            {
-                log.info( "Repository {} is already member of group {}", repositoryId, repositoryGroupId );
-                return RepositoryGroup.of( editableRepositoryGroup );
-            }
-            org.apache.archiva.repository.ManagedRepository managedRepo = repositoryRegistry.getManagedRepository( repositoryId );
-            if ( managedRepo == null )
-            {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, "" ), 404 );
-            }
-            editableRepositoryGroup.addRepository( managedRepo );
-            org.apache.archiva.repository.RepositoryGroup newGroup = repositoryRegistry.putRepositoryGroup( editableRepositoryGroup );
-            return RepositoryGroup.of( newGroup );
-        }
-        catch ( RepositoryException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage( ) ), 500 );
-        }
-    }
-
-    @Override
-    public RepositoryGroup deleteRepositoryFromGroup( final String repositoryGroupId, final String repositoryId ) throws org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException
-    {
-        if ( StringUtils.isEmpty( repositoryGroupId ) )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, repositoryGroupId ), 404 );
-        }
-        if ( StringUtils.isEmpty( repositoryId ) )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
-        }
-        try
-        {
-            org.apache.archiva.repository.RepositoryGroup repositoryGroup = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
-            if ( repositoryGroup == null )
-            {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
-            }
-            if ( repositoryGroup.getRepositories( ).stream( ).noneMatch( r -> repositoryId.equals( r.getId( ) ) ) )
-            {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
-            }
-            if ( !( repositoryGroup instanceof EditableRepositoryGroup ) )
-            {
-                log.error( "This group instance is not editable: {}", repositoryGroupId );
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, "" ), 500 );
-            }
-            EditableRepositoryGroup editableRepositoryGroup = (EditableRepositoryGroup) repositoryGroup;
-            editableRepositoryGroup.removeRepository( repositoryId );
-            org.apache.archiva.repository.RepositoryGroup newGroup = repositoryRegistry.putRepositoryGroup( editableRepositoryGroup );
-            return RepositoryGroup.of( newGroup );
-        }
-        catch ( RepositoryException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage( ) ), 500 );
-        }
-    }
-
-
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java
deleted file mode 100644 (file)
index da498c2..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-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 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.rest.util.RestUtil;
-import org.apache.archiva.metadata.repository.MetadataRepositoryException;
-import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager;
-import org.apache.archiva.repository.RemoteRepository;
-import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.scanner.RepositoryScanner;
-import org.apache.archiva.repository.scanner.RepositoryScannerException;
-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.DownloadRemoteIndexException;
-import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexScheduler;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-import javax.inject.Named;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Locale;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- * @since 3.0
- */
-@Service( "v2.repositoryService#rest" )
-public class DefaultRepositoryService implements RepositoryService
-{
-
-    final
-    RepositoryRegistry repositoryRegistry;
-
-    final
-    RepositoryStatisticsManager repositoryStatisticsManager;
-
-    private final RepositoryTaskAdministration repositoryTaskAdministration;
-
-    private final RepositoryScanner repoScanner;
-
-    private final DownloadRemoteIndexScheduler downloadRemoteIndexScheduler;
-
-    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, DownloadRemoteIndexScheduler downloadRemoteIndexScheduler )
-    {
-        this.repositoryRegistry = repositoryRegistry;
-        this.repositoryStatisticsManager = repositoryStatisticsManager;
-        this.repoScanner = repoScanner;
-        this.repositoryTaskAdministration = repositoryTaskAdministration;
-        this.downloadRemoteIndexScheduler = downloadRemoteIndexScheduler;
-    }
-
-    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
-    {
-        final Locale locale = StringUtils.isNotEmpty( localeString ) ? Locale.forLanguageTag( localeString ) : Locale.getDefault( );
-        boolean isAscending = QUERY_HELPER.isAscending( order );
-        Predicate<org.apache.archiva.repository.Repository> filter = QUERY_HELPER.getQueryFilter( searchTerm );
-        Comparator<org.apache.archiva.repository.Repository> comparator = QUERY_HELPER.getComparator( orderBy, isAscending );
-        try
-        {
-            int totalCount = Math.toIntExact( repositoryRegistry.getRepositories( ).stream( ).filter( filter ).count( ) );
-            return new PagedResult<>( totalCount, offset, limit, repositoryRegistry.getRepositories( ).stream( )
-                .filter( filter ).skip( offset ).limit( limit ).sorted( comparator ).map( repo -> Repository.of( repo, locale ) )
-                .collect( Collectors.toList( ) ) );
-        }
-        catch ( ArithmeticException e )
-        {
-            log.error( "Invalid integer conversion for totalCount" );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) );
-        }
-    }
-
-    @Override
-    public RepositoryStatistics getManagedRepositoryStatistics( String repositoryId ) throws ArchivaRestServiceException
-    {
-        if ( repositoryRegistry.getManagedRepository( repositoryId ) == null )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_MANAGED_NOT_FOUND, repositoryId ), 404 );
-        }
-        try
-        {
-            return RepositoryStatistics.of( repositoryStatisticsManager.getLastStatistics( repositoryId ) );
-        }
-        catch ( MetadataRepositoryException e )
-        {
-            log.error( "Metadata error: {} ", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_METADATA_ERROR, e.getMessage( ) ) );
-        }
-    }
-
-    @Override
-    public Response scheduleRepositoryScan( String repositoryId, boolean fullScan ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            repositoryTaskAdministration.scheduleFullScan( repositoryId );
-            return Response.ok( ).build( );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            handleAdminException( e );
-            return Response.serverError( ).build( );
-        }
-    }
-
-    @Override
-    public RepositoryStatistics scanRepositoryImmediately( String repositoryId ) throws ArchivaRestServiceException
-    {
-        long sinceWhen = RepositoryScanner.FRESH_SCAN;
-        try
-        {
-            return RepositoryStatistics.of( repoScanner.scan( repositoryRegistry.getManagedRepository( repositoryId ), sinceWhen ) );
-        }
-        catch ( RepositoryScannerException e )
-        {
-            log.error( e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_SCAN_FAILED, e.getMessage( ) ) );
-        }
-    }
-
-    @Override
-    public ScanStatus getScanStatus( String repositoryId ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            return ScanStatus.of( repositoryTaskAdministration.getCurrentScanStatus( ) );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            handleAdminException( e );
-            return new ScanStatus();
-        }
-    }
-
-    @Override
-    public Response removeScanningTaskFromQueue( String repositoryId ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            repositoryTaskAdministration.cancelTasks( repositoryId );
-            return Response.ok( ).build( );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            handleAdminException( e );
-            return Response.serverError( ).build( );
-        }
-    }
-
-
-    @Override
-    public Response scheduleDownloadRemoteIndex( String repositoryId, boolean immediately, boolean full,
-                                                 UriInfo uriInfo ) throws ArchivaRestServiceException
-    {
-        boolean immediateSet = RestUtil.isFlagSet( uriInfo, "immediate" );
-        boolean fullSet = RestUtil.isFlagSet( uriInfo, "full" );
-        RemoteRepository repo = repositoryRegistry.getRemoteRepository( repositoryId );
-        if (repo==null) {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_NOT_FOUND, repositoryId ), 404 );
-        }
-        try
-        {
-            downloadRemoteIndexScheduler.scheduleDownloadRemote( repositoryId, immediateSet, fullSet );
-            return Response.ok( ).build( );
-        }
-        catch ( DownloadRemoteIndexException e )
-        {
-            log.error( "Could not schedule index download for repository {}: {}", repositoryId, e.getMessage(), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED, e.getMessage( ) ) );
-        }
-    }
-
-
-
-    @Override
-    public List<String> getRunningRemoteDownloads( )
-    {
-        return downloadRemoteIndexScheduler.getRunningRemoteDownloadIds( );
-    }
-}
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
deleted file mode 100644 (file)
index 360d03e..0000000
+++ /dev/null
@@ -1,677 +0,0 @@
-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.
- */
-
-/*
- * 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.RedbackRuntimeConfiguration;
-import org.apache.archiva.admin.model.runtime.RedbackRuntimeConfigurationAdmin;
-import org.apache.archiva.components.rest.model.PagedResult;
-import org.apache.archiva.components.rest.model.PropertyEntry;
-import org.apache.archiva.components.rest.util.QueryHelper;
-import org.apache.archiva.redback.authentication.Authenticator;
-import org.apache.archiva.redback.common.ldap.connection.LdapConnection;
-import org.apache.archiva.redback.common.ldap.connection.LdapConnectionConfiguration;
-import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory;
-import org.apache.archiva.redback.common.ldap.connection.LdapException;
-import org.apache.archiva.redback.common.ldap.user.LdapUserMapper;
-import org.apache.archiva.redback.policy.CookieSettings;
-import org.apache.archiva.redback.policy.PasswordRule;
-import org.apache.archiva.redback.rbac.RBACManager;
-import org.apache.archiva.redback.role.RoleManager;
-import org.apache.archiva.redback.users.UserManager;
-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.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;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.naming.AuthenticationException;
-import javax.naming.AuthenticationNotSupportedException;
-import javax.naming.CommunicationException;
-import javax.naming.InvalidNameException;
-import javax.naming.NamingException;
-import javax.naming.NoPermissionException;
-import javax.naming.ServiceUnavailableException;
-import javax.ws.rs.core.Response;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.ResourceBundle;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-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>
- */
-@Service( "v2.defaultSecurityConfigurationService" )
-public class DefaultSecurityConfigurationService implements SecurityConfigurationService
-{
-    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 final List<String> availableContextProviders = new ArrayList<>( );
-
-    private static final QueryHelper<PropertyEntry> PROP_QUERY_HELPER = new QueryHelper<>( new String[]{"key"} );
-
-    static
-    {
-        PROP_QUERY_HELPER.addStringFilter( "key", PropertyEntry::getKey );
-        PROP_QUERY_HELPER.addStringFilter( "value", PropertyEntry::getValue );
-        PROP_QUERY_HELPER.addNullsafeFieldComparator( "key", PropertyEntry::getKey );
-        PROP_QUERY_HELPER.addNullsafeFieldComparator( "value", PropertyEntry::getValue );
-
-    }
-
-    private ResourceBundle bundle;
-
-
-    @Inject
-    private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin;
-
-    @Inject
-    private ApplicationContext applicationContext;
-
-    @Inject
-    @Named( value = "userManager#default" )
-    private UserManager userManager;
-
-    @Inject
-    @Named( value = "rbacManager#default" )
-    private RBACManager rbacManager;
-
-    @Inject
-    private RoleManager roleManager;
-
-    @Inject
-    @Named( value = "ldapConnectionFactory#configurable" )
-    private LdapConnectionFactory ldapConnectionFactory;
-
-    @Inject
-    private LdapUserMapper ldapUserMapper;
-
-
-    @PostConstruct
-    void init( )
-    {
-        bundle = ResourceBundle.getBundle( "org.apache.archiva.rest.RestBundle" );
-        for (String ldapClass : KNOWN_LDAP_CONTEXT_PROVIDERS) {
-            if (isContextFactoryAvailable( ldapClass )) {
-                availableContextProviders.add( ldapClass );
-            }
-        }
-    }
-
-    @Override
-    public SecurityConfiguration getConfiguration( ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
-                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
-
-            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
-
-            return SecurityConfiguration.ofRedbackConfiguration( redbackRuntimeConfiguration );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
-        }
-    }
-
-    private void updateConfig( SecurityConfiguration newConfig, RedbackRuntimeConfiguration rbConfig )
-    {
-        rbConfig.setUserManagerImpls( newConfig.getActiveUserManagers( ) );
-        rbConfig.setRbacManagerImpls( newConfig.getActiveRbacManagers( ) );
-        rbConfig.setUseUsersCache( newConfig.isUserCacheEnabled( ) );
-        Map<String, String> props = rbConfig.getConfigurationProperties( );
-        for ( Map.Entry<String, String> newProp : newConfig.getProperties( ).entrySet( ) )
-        {
-            props.put( newProp.getKey( ), newProp.getValue( ) );
-        }
-    }
-
-    private void updateConfig( LdapConfiguration newConfig, RedbackRuntimeConfiguration rbConfig )
-    {
-        org.apache.archiva.admin.model.beans.LdapConfiguration ldapConfig = rbConfig.getLdapConfiguration( );
-        ldapConfig.setBaseDn( newConfig.getBaseDn( ) );
-        ldapConfig.setAuthenticationMethod( newConfig.getAuthenticationMethod( ) );
-        ldapConfig.setBindAuthenticatorEnabled( newConfig.isBindAuthenticatorEnabled( ) );
-        ldapConfig.setBindDn( newConfig.getBindDn( ) );
-        ldapConfig.setSsl( newConfig.isSslEnabled( ) );
-        ldapConfig.setBaseGroupsDn( newConfig.getGroupsBaseDn( ) );
-        ldapConfig.setHostName( newConfig.getHostName( ) );
-        ldapConfig.setPort( newConfig.getPort( ) );
-        ldapConfig.setPassword( newConfig.getBindPassword( ) );
-        ldapConfig.setUseRoleNameAsGroup( newConfig.isUseRoleNameAsGroup( ) );
-        ldapConfig.setWritable( newConfig.isWritable( ) );
-        ldapConfig.setContextFactory( newConfig.getContextFactory( ) );
-
-        Map<String, String> props = ldapConfig.getExtraProperties( );
-        for ( Map.Entry<String, String> newProp : newConfig.getProperties( ).entrySet( ) )
-        {
-            props.put( newProp.getKey( ), newProp.getValue( ) );
-        }
-    }
-
-    private void updateConfig( CacheConfiguration newConfig, RedbackRuntimeConfiguration rbConfig )
-    {
-        org.apache.archiva.admin.model.beans.CacheConfiguration cacheConfig = rbConfig.getUsersCacheConfiguration( );
-        cacheConfig.setMaxElementsInMemory( newConfig.getMaxEntriesInMemory( ) );
-        cacheConfig.setMaxElementsOnDisk( newConfig.getMaxEntriesOnDisk( ) );
-        cacheConfig.setTimeToLiveSeconds( newConfig.getTimeToLiveSeconds( ) );
-        cacheConfig.setTimeToIdleSeconds( newConfig.getTimeToIdleSeconds( ) );
-    }
-
-    @Override
-    public SecurityConfiguration updateConfiguration( SecurityConfiguration newConfiguration ) throws ArchivaRestServiceException
-    {
-        if ( newConfiguration == null )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 );
-        }
-        try
-        {
-            RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
-            boolean userManagerChanged = !CollectionUtils.isEqualCollection( newConfiguration.getActiveUserManagers( ), conf.getUserManagerImpls( ) );
-            boolean rbacManagerChanged = !CollectionUtils.isEqualCollection( newConfiguration.getActiveRbacManagers( ), conf.getRbacManagerImpls( ) );
-
-            boolean ldapConfigured = newConfiguration.getActiveUserManagers( ).stream( ).anyMatch( um -> um.contains( "ldap" ) );
-            if ( !ldapConfigured )
-            {
-                ldapConfigured= newConfiguration.getActiveRbacManagers( ).stream( ).anyMatch( um -> um.contains( "ldap" ) );
-            }
-
-            updateConfig( newConfiguration, conf );
-            redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( conf );
-
-            if ( userManagerChanged )
-            {
-                log.info( "user managerImpls changed to {} so reload it",
-                    newConfiguration.getActiveUserManagers( ) );
-                userManager.initialize( );
-            }
-
-            if ( rbacManagerChanged )
-            {
-                log.info( "rbac manager changed to {} so reload it",
-                    newConfiguration.getActiveRbacManagers( ) );
-                rbacManager.initialize( );
-                roleManager.initialize( );
-            }
-
-            if ( ldapConfigured )
-            {
-                try
-                {
-                    ldapConnectionFactory.initialize( );
-                }
-                catch ( Exception e )
-                {
-                    log.error( "Could not initialize LDAP connection factory: {}", e.getMessage( ) );
-                    throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_CF_INIT_FAILED, e.getMessage( ) ) );
-                }
-            }
-            Collection<PasswordRule> passwordRules = applicationContext.getBeansOfType( PasswordRule.class ).values( );
-
-            for ( PasswordRule passwordRule : passwordRules )
-            {
-                passwordRule.initialize( );
-            }
-
-            Collection<CookieSettings> cookieSettingsList =
-                applicationContext.getBeansOfType( CookieSettings.class ).values( );
-
-            for ( CookieSettings cookieSettings : cookieSettingsList )
-            {
-                cookieSettings.initialize( );
-            }
-
-            Collection<Authenticator> authenticators =
-                applicationContext.getBeansOfType( Authenticator.class ).values( );
-
-            for ( Authenticator authenticator : authenticators )
-            {
-                try
-                {
-                    log.debug( "Initializing authenticatior " + authenticator.getId( ) );
-                    authenticator.initialize( );
-                }
-                catch ( Exception e )
-                {
-                    log.error( "Initialization of authenticator failed " + authenticator.getId( ), e );
-                }
-            }
-
-            if ( ldapConfigured )
-            {
-                try
-                {
-                    ldapUserMapper.initialize( );
-                }
-                catch ( Exception e )
-                {
-                    throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_USER_MAPPER_INIT_FAILED, e.getMessage( ) ) );
-                }
-            }
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
-        }
-        try
-        {
-            return SecurityConfiguration.ofRedbackConfiguration( redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ) );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            log.error( "Error while retrieve updated configuration: {}", e.getMessage( ) );
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
-        }
-    }
-
-    @Override
-    public PagedResult<PropertyEntry> getConfigurationProperties( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
-                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
-
-            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
-
-            boolean ascending = PROP_QUERY_HELPER.isAscending( order );
-            Predicate<PropertyEntry> filter = PROP_QUERY_HELPER.getQueryFilter( searchTerm );
-            Comparator<PropertyEntry> comparator = PROP_QUERY_HELPER.getComparator( orderBy, ascending );
-            Map<String, String> props = redbackRuntimeConfiguration.getConfigurationProperties( );
-            int totalCount = Math.toIntExact( props.entrySet( ).stream( ).map(
-                entry -> new PropertyEntry( entry.getKey( ), entry.getValue( ) )
-            ).filter( filter ).count( ) );
-            List<PropertyEntry> result = props.entrySet( ).stream( ).map(
-                entry -> new PropertyEntry( entry.getKey( ), entry.getValue( ) )
-            ).filter( filter )
-                .sorted( comparator )
-                .skip( offset ).limit( limit )
-                .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!" );
-            throw new ArchivaRestServiceException( ErrorMessage.of( INVALID_RESULT_SET_ERROR ) );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
-        }
-    }
-
-    @Override
-    public PropertyEntry getConfigurationProperty( String propertyName ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
-            if ( conf.getConfigurationProperties( ).containsKey( propertyName ) )
-            {
-                String value = conf.getConfigurationProperties( ).get( propertyName );
-                return new PropertyEntry( propertyName, value );
-            }
-            else
-            {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PROPERTY_NOT_FOUND ), 404 );
-            }
-
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
-        }
-
-    }
-
-    @Override
-    public Response updateConfigurationProperty( String propertyName, PropertyEntry propertyValue ) throws ArchivaRestServiceException
-    {
-        if ( propertyValue == null )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 );
-        }
-        try
-        {
-            RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
-            if ( conf.getConfigurationProperties( ).containsKey( propertyName ) )
-            {
-                conf.getConfigurationProperties( ).put( propertyName, propertyValue.getValue( ) );
-                redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( conf );
-                return Response.ok( ).build( );
-            }
-            else
-            {
-                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PROPERTY_NOT_FOUND ), 404 );
-            }
-
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
-        }
-    }
-
-    @Override
-    public LdapConfiguration getLdapConfiguration( ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
-                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
-
-            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
-
-            LdapConfiguration ldapConfig = LdapConfiguration.of( redbackRuntimeConfiguration.getLdapConfiguration( ) );
-            ldapConfig.setAvailableContextFactories( availableContextProviders );
-            return ldapConfig;
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
-        }
-
-    }
-
-    @Override
-    public LdapConfiguration updateLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
-                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
-
-            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
-
-            updateConfig( configuration, redbackRuntimeConfiguration );
-
-            redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration );
-            ldapConnectionFactory.initialize( );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
-        }
-
-        try
-        {
-            return LdapConfiguration.of( redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ).getLdapConfiguration() );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            log.error( "Error while retrieve updated configuration: {}", e.getMessage( ) );
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
-        }
-
-    }
-
-    static Properties toProperties( Map<String, String> values )
-    {
-        Properties result = new Properties( );
-        for ( Map.Entry<String, String> entry : values.entrySet( ) )
-        {
-            result.setProperty( entry.getKey( ), entry.getValue( ) );
-        }
-        return result;
-    }
-
-    private static boolean isContextFactoryAvailable( final String factoryClass)
-    {
-        try
-        {
-            return Thread.currentThread().getContextClassLoader().loadClass( factoryClass )
-                != null;
-        }
-        catch ( ClassNotFoundException e )
-        {
-            return false;
-        }
-    }
-
-
-    @Override
-    public Response verifyLdapConfiguration( LdapConfiguration ldapConfiguration ) throws ArchivaRestServiceException
-    {
-        LdapConnection ldapConnection = null;
-        try
-        {
-            LdapConnectionConfiguration ldapConnectionConfiguration =
-                new LdapConnectionConfiguration( ldapConfiguration.getHostName( ), ldapConfiguration.getPort( ),
-                    ldapConfiguration.getBaseDn( ), ldapConfiguration.getContextFactory( ),
-                    ldapConfiguration.getBindDn( ), ldapConfiguration.getBindPassword( ),
-                    ldapConfiguration.getAuthenticationMethod( ),
-                    toProperties( ldapConfiguration.getProperties( ) ) );
-            ldapConnectionConfiguration.setSsl( ldapConfiguration.isSslEnabled( ) );
-
-            ldapConnection = ldapConnectionFactory.getConnection( ldapConnectionConfiguration );
-        }
-        catch ( InvalidNameException e )
-        {
-            log.warn( "LDAP connection check failed with invalid name : {}", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_INVALID_NAME, e.getMessage( ) ), 400 );
-        }
-        catch ( LdapException e )
-        {
-            handleLdapException( e );
-        }
-        finally
-        {
-            if ( ldapConnection != null )
-            {
-                try
-                {
-                    ldapConnection.close( );
-                }
-                catch ( NamingException e )
-                {
-                    log.error( "Could not close connection: {}", e.getMessage( ) );
-                }
-            }
-            ldapConnection = null;
-        }
-
-        try
-        {
-            // verify groups dn value too
-
-            LdapConnectionConfiguration ldapConnectionConfiguration = new LdapConnectionConfiguration( ldapConfiguration.getHostName( ), ldapConfiguration.getPort( ),
-                ldapConfiguration.getGroupsBaseDn( ),
-                ldapConfiguration.getContextFactory( ), ldapConfiguration.getBindDn( ),
-                ldapConfiguration.getBindPassword( ),
-                ldapConfiguration.getAuthenticationMethod( ),
-                toProperties( ldapConfiguration.getProperties( ) ) );
-
-            ldapConnectionConfiguration.setSsl( ldapConfiguration.isSslEnabled( ) );
-
-            ldapConnection = ldapConnectionFactory.getConnection( ldapConnectionConfiguration );
-        }
-        catch ( InvalidNameException e )
-        {
-            log.warn( "LDAP connection check failed with invalid name : {}", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_INVALID_NAME, e.getMessage( ) ), 400 );
-        }
-        catch ( LdapException e )
-        {
-            handleLdapException( e );
-        }
-        finally
-        {
-            if ( ldapConnection != null )
-            {
-                try
-                {
-                    ldapConnection.close( );
-                }
-                catch ( NamingException e )
-                {
-                    log.error( "Could not close connection: {}", e.getMessage( ), e );
-                }
-            }
-        }
-
-        return Response.ok( ).build( );
-    }
-
-    private void handleLdapException( LdapException e ) throws ArchivaRestServiceException
-    {
-        Throwable rootCause = e.getRootCause( );
-        if ( rootCause instanceof CommunicationException )
-        {
-            log.warn( "LDAP connection check failed with CommunicationException: {}", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_COMMUNICATION_ERROR, e.getMessage( ) ), 400 );
-        } else if (rootCause instanceof ServiceUnavailableException ) {
-            log.warn( "LDAP connection check failed with ServiceUnavailableException: {}", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_UNAVAILABLE, e.getMessage( ) ), 400 );
-        } else if (rootCause instanceof AuthenticationException ) {
-            log.warn( "LDAP connection check failed with AuthenticationException: {}", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_AUTHENTICATION_FAILED, e.getMessage( ) ), 400 );
-        } else if (rootCause instanceof AuthenticationNotSupportedException ) {
-            log.warn( "LDAP connection check failed with AuthenticationNotSupportedException: {}", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_AUTHENTICATION_NOT_SUPPORTED, e.getMessage( ) ), 400 );
-        } else if (rootCause instanceof NoPermissionException ) {
-            log.warn( "LDAP connection check failed with NoPermissionException: {}", e.getMessage( ), e );
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_NO_PERMISSION, e.getMessage( ) ), 400 );
-        }
-        log.warn( "LDAP connection check failed: {} - {}", e.getClass().getName(), e.getMessage( ), e );
-        throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_GENERIC_ERROR, e.getMessage( ) ), 400 );
-    }
-
-    @Override
-    public CacheConfiguration getCacheConfiguration( ) throws ArchivaRestServiceException
-    {
-        try
-        {
-            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
-                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
-
-            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
-
-            return CacheConfiguration.of( redbackRuntimeConfiguration.getUsersCacheConfiguration( ) );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
-        }
-
-    }
-
-    @Override
-    public CacheConfiguration updateCacheConfiguration( CacheConfiguration cacheConfiguration ) throws ArchivaRestServiceException
-    {
-        if ( cacheConfiguration == null )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 );
-        }
-        try
-        {
-            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
-                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
-
-            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
-            updateConfig( cacheConfiguration, redbackRuntimeConfiguration );
-            redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration );
-            return getCacheConfiguration( );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
-        }
-    }
-
-    @Override
-    public List<BeanInformation> getAvailableUserManagers( )
-    {
-        Map<String, UserManager> beans = applicationContext.getBeansOfType( UserManager.class );
-
-        if ( beans.isEmpty( ) )
-        {
-            return Collections.emptyList( );
-        }
-
-        return beans.entrySet( ).stream( )
-            .filter( entry -> entry.getValue( ).isFinalImplementation( ) )
-            .map( ( Map.Entry<String, UserManager> entry ) -> {
-                UserManager um = entry.getValue( );
-                String id = StringUtils.substringAfter( entry.getKey( ), "#" );
-                String displayName = bundle.getString( "user_manager." + id + ".display_name" );
-                String description = bundle.getString( "user_manager." + id + ".description" );
-                return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, um.getDescriptionKey( ), description, um.isReadOnly( ) );
-            } ).collect( Collectors.toList( ) );
-    }
-
-    @Override
-    public List<BeanInformation> getAvailableRbacManagers( )
-    {
-        Map<String, RBACManager> beans = applicationContext.getBeansOfType( RBACManager.class );
-
-        if ( beans.isEmpty( ) )
-        {
-            return Collections.emptyList( );
-        }
-
-        return beans.entrySet( ).stream( )
-            .filter( entry -> entry.getValue( ).isFinalImplementation( ) )
-            .map( ( Map.Entry<String, RBACManager> entry ) -> {
-                RBACManager rm = entry.getValue( );
-                String id = StringUtils.substringAfter( entry.getKey( ), "#" );
-                String displayName = bundle.getString( "rbac_manager." + id + ".display_name" );
-                String description = bundle.getString( "rbac_manager." + id + ".description" );
-                return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, rm.getDescriptionKey( ), description, rm.isReadOnly( ) );
-            } ).collect( Collectors.toList( ) );
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/ArchivaRestServiceExceptionMapper.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/ArchivaRestServiceExceptionMapper.java
new file mode 100644 (file)
index 0000000..096e8fd
--- /dev/null
@@ -0,0 +1,67 @@
+package org.apache.archiva.rest.v2.interceptor;
+/*
+ * 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.rest.api.v2.svc.ArchivaRestError;
+import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException;
+import org.springframework.stereotype.Service;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Maps exceptions to REST responses.
+ *
+ * @author Martin Stockhammer
+ * @since 3.0
+ */
+@Provider
+@Service( "v2.archivaRestServiceExceptionMapper" )
+public class ArchivaRestServiceExceptionMapper
+    implements ExceptionMapper<ArchivaRestServiceException>
+{
+    @Override
+    public Response toResponse( final ArchivaRestServiceException e )
+    {
+        ArchivaRestError restError = new ArchivaRestError( e );
+
+        Response.ResponseBuilder responseBuilder = Response.status( e.getHttpErrorCode() ).entity( restError );
+        if ( e.getMessage() != null )
+        {
+            responseBuilder = responseBuilder.status( new Response.StatusType()
+            {
+                public int getStatusCode()
+                {
+                    return e.getHttpErrorCode();
+                }
+
+                public Response.Status.Family getFamily()
+                {
+                    return Response.Status.Family.familyOf( e.getHttpErrorCode( ) );
+                }
+
+                public String getReasonPhrase()
+                {
+                    return e.getMessage();
+                }
+            } );
+        }
+        return responseBuilder.build();
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultMavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultMavenManagedRepositoryService.java
new file mode 100644 (file)
index 0000000..0c67cd4
--- /dev/null
@@ -0,0 +1,389 @@
+package org.apache.archiva.rest.v2.svc;
+/*
+ * 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.AuditInformation;
+import org.apache.archiva.admin.model.RepositoryAdminException;
+import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
+import org.apache.archiva.components.rest.model.PagedResult;
+import org.apache.archiva.components.rest.util.QueryHelper;
+import org.apache.archiva.redback.authentication.AuthenticationResult;
+import org.apache.archiva.redback.authorization.AuthorizationException;
+import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal;
+import org.apache.archiva.redback.rest.services.RedbackRequestInformation;
+import org.apache.archiva.redback.system.DefaultSecuritySession;
+import org.apache.archiva.redback.system.SecuritySession;
+import org.apache.archiva.redback.system.SecuritySystem;
+import org.apache.archiva.redback.users.User;
+import org.apache.archiva.redback.users.UserManagerException;
+import org.apache.archiva.redback.users.UserNotFoundException;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.ReleaseScheme;
+import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryRegistry;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.content.ContentItem;
+import org.apache.archiva.repository.content.LayoutException;
+import org.apache.archiva.repository.storage.fs.FsStorageUtil;
+import org.apache.archiva.rest.api.v2.model.FileInfo;
+import org.apache.archiva.rest.api.v2.model.MavenManagedRepository;
+import org.apache.archiva.rest.api.v2.model.MavenManagedRepositoryUpdate;
+import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException;
+import org.apache.archiva.rest.api.v2.svc.ErrorKeys;
+import org.apache.archiva.rest.api.v2.svc.ErrorMessage;
+import org.apache.archiva.rest.api.v2.svc.maven.MavenManagedRepositoryService;
+import org.apache.archiva.security.common.ArchivaRoleConstants;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS;
+import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Service("v2.managedMavenRepositoryService#rest")
+public class DefaultMavenManagedRepositoryService implements MavenManagedRepositoryService
+{
+    @Context
+    HttpServletResponse httpServletResponse;
+
+    @Context
+    UriInfo uriInfo;
+
+    private static final Logger log = LoggerFactory.getLogger( DefaultMavenManagedRepositoryService.class );
+    private static final QueryHelper<ManagedRepository> QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} );
+    static
+    {
+        QUERY_HELPER.addStringFilter( "id", ManagedRepository::getId );
+        QUERY_HELPER.addStringFilter( "name", ManagedRepository::getName );
+        QUERY_HELPER.addStringFilter( "location", (r)  -> r.getLocation().toString() );
+        QUERY_HELPER.addBooleanFilter( "snapshot", (r) -> r.getActiveReleaseSchemes( ).contains( ReleaseScheme.SNAPSHOT ) );
+        QUERY_HELPER.addBooleanFilter( "release", (r) -> r.getActiveReleaseSchemes().contains( ReleaseScheme.RELEASE ));
+        QUERY_HELPER.addNullsafeFieldComparator( "id", ManagedRepository::getId );
+        QUERY_HELPER.addNullsafeFieldComparator( "name", ManagedRepository::getName );
+    }
+
+    private ManagedRepositoryAdmin managedRepositoryAdmin;
+    private RepositoryRegistry repositoryRegistry;
+    private SecuritySystem securitySystem;
+
+    public DefaultMavenManagedRepositoryService( SecuritySystem securitySystem,
+                                                 RepositoryRegistry repositoryRegistry,
+                                                 ManagedRepositoryAdmin managedRepositoryAdmin )
+    {
+        this.securitySystem = securitySystem;
+        this.repositoryRegistry = repositoryRegistry;
+        this.managedRepositoryAdmin = managedRepositoryAdmin;
+    }
+
+    protected AuditInformation getAuditInformation( )
+    {
+        RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get( );
+        User user;
+        String remoteAddr;
+        if (redbackRequestInformation==null) {
+            user = null;
+            remoteAddr = null;
+        } else
+        {
+            user = redbackRequestInformation.getUser( );
+            remoteAddr = redbackRequestInformation.getRemoteAddr( );
+        }
+        return new AuditInformation( user, remoteAddr );
+    }
+
+    @Override
+    public PagedResult<MavenManagedRepository> getManagedRepositories( final String searchTerm, final Integer offset,
+                                                                       final Integer limit, final List<String> orderBy,
+                                                                       final String order ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            Collection<ManagedRepository> repos = repositoryRegistry.getManagedRepositories( );
+            final Predicate<ManagedRepository> queryFilter = QUERY_HELPER.getQueryFilter( searchTerm ).and( r -> r.getType() == RepositoryType.MAVEN );
+            final Comparator<ManagedRepository> comparator = QUERY_HELPER.getComparator( orderBy, order );
+            int totalCount = Math.toIntExact( repos.stream( ).filter( queryFilter ).count( ) );
+            return PagedResult.of( totalCount, offset, limit, repos.stream( ).filter( queryFilter ).sorted( comparator )
+                .map(mr -> MavenManagedRepository.of(mr)).skip( offset ).limit( limit ).collect( Collectors.toList( ) ) );
+        }
+        catch (ArithmeticException e) {
+            log.error( "Invalid number of repositories detected." );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) );
+        }
+    }
+
+    @Override
+    public MavenManagedRepository getManagedRepository( String repositoryId ) throws ArchivaRestServiceException
+    {
+        ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId );
+        if (repo==null) {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
+        }
+        if (repo.getType()!=RepositoryType.MAVEN) {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 );
+        }
+        return MavenManagedRepository.of( repo );
+    }
+
+    @Override
+    public Response deleteManagedRepository( String repositoryId, boolean deleteContent ) throws ArchivaRestServiceException
+    {
+        ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId );
+        if (repo==null) {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
+        }
+        if (repo.getType()!=RepositoryType.MAVEN) {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 );
+        }
+        try
+        {
+            managedRepositoryAdmin.deleteManagedRepository( repositoryId, getAuditInformation( ), deleteContent );
+            return Response.ok( ).build( );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_DELETE_FAILED, e.getMessage( ) ) );
+        }
+    }
+
+    private org.apache.archiva.admin.model.beans.ManagedRepository convert(MavenManagedRepository repository) {
+        org.apache.archiva.admin.model.beans.ManagedRepository repoBean = new org.apache.archiva.admin.model.beans.ManagedRepository( );
+        repoBean.setId( repository.getId( ) );
+        repoBean.setName( repository.getName() );
+        repoBean.setDescription( repository.getDescription() );
+        repoBean.setBlockRedeployments( repository.isBlocksRedeployments() );
+        repoBean.setCronExpression( repository.getSchedulingDefinition() );
+        repoBean.setLocation( repository.getLocation() );
+        repoBean.setReleases( repository.getReleaseSchemes().contains( ReleaseScheme.RELEASE.name() ) );
+        repoBean.setSnapshots( repository.getReleaseSchemes().contains( ReleaseScheme.SNAPSHOT.name() ) );
+        repoBean.setScanned( repository.isScanned() );
+        repoBean.setDeleteReleasedSnapshots( repository.isDeleteSnapshotsOfRelease() );
+        repoBean.setSkipPackedIndexCreation( repository.isSkipPackedIndexCreation() );
+        repoBean.setRetentionCount( repository.getRetentionCount() );
+        repoBean.setRetentionPeriod( repository.getRetentionPeriod().getDays() );
+        repoBean.setIndexDirectory( repository.getIndexPath() );
+        repoBean.setPackedIndexDirectory( repository.getPackedIndexPath() );
+        repoBean.setLayout( repository.getLayout() );
+        repoBean.setType( RepositoryType.MAVEN.name( ) );
+        return repoBean;
+    }
+
+    @Override
+    public MavenManagedRepository addManagedRepository( MavenManagedRepository managedRepository ) throws ArchivaRestServiceException
+    {
+        final String repoId = managedRepository.getId( );
+        if ( StringUtils.isEmpty( repoId ) ) {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_INVALID_ID, repoId ), 422 );
+        }
+        Repository repo = repositoryRegistry.getRepository( repoId );
+        if (repo!=null) {
+            httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( repoId ).build( ).toString( ) );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ID_EXISTS, repoId ), 303 );
+        }
+        try
+        {
+            managedRepositoryAdmin.addManagedRepository( convert( managedRepository ), managedRepository.isHasStagingRepository(), getAuditInformation() );
+            httpServletResponse.setStatus( 201 );
+            return MavenManagedRepository.of( repositoryRegistry.getManagedRepository( repoId ) );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+        }
+    }
+
+    @Override
+    public MavenManagedRepository updateManagedRepository( final String repositoryId, final MavenManagedRepositoryUpdate managedRepository ) throws ArchivaRestServiceException
+    {
+        org.apache.archiva.admin.model.beans.ManagedRepository repo = convert( managedRepository );
+        try
+        {
+            managedRepositoryAdmin.updateManagedRepository( repo, managedRepository.isHasStagingRepository( ), getAuditInformation( ), managedRepository.isResetStats( ) );
+            ManagedRepository newRepo = repositoryRegistry.getManagedRepository( managedRepository.getId( ) );
+            if (newRepo==null) {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_UPDATE_FAILED, repositoryId ) );
+            }
+            return MavenManagedRepository.of( newRepo );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+        }
+    }
+
+    @Override
+    public FileInfo getFileStatus( String repositoryId, String fileLocation ) throws ArchivaRestServiceException
+    {
+        ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId );
+        if (repo==null) {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
+        }
+        try
+        {
+            ContentItem contentItem = repo.getContent( ).toItem( fileLocation );
+            if (contentItem.getAsset( ).exists( ))  {
+                return FileInfo.of( contentItem.getAsset( ) );
+            } else {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_NOT_FOUND, repositoryId, fileLocation ), 404 );
+            }
+        }
+        catch ( LayoutException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_LAYOUT_ERROR, e.getMessage( ) ) );
+        }
+    }
+
+    @Override
+    public Response copyArtifact( String srcRepositoryId, String dstRepositoryId,
+                                  String path ) throws ArchivaRestServiceException
+    {
+        final AuditInformation auditInformation = getAuditInformation( );
+        final String userName = auditInformation.getUser( ).getUsername( );
+        if ( StringUtils.isEmpty( userName ) )
+        {
+            httpServletResponse.setHeader( "WWW-Authenticate", "Bearer realm=\"archiva\"" );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.NOT_AUTHENTICATED ), 401 );
+        }
+        ManagedRepository srcRepo = repositoryRegistry.getManagedRepository( srcRepositoryId );
+        if (srcRepo==null) {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, srcRepositoryId ), 404 );
+        }
+        ManagedRepository dstRepo = repositoryRegistry.getManagedRepository( dstRepositoryId );
+        if (dstRepo==null) {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, dstRepositoryId ), 404 );
+        }
+        checkAuthority( auditInformation.getUser().getUsername(), srcRepositoryId, dstRepositoryId );
+        try
+        {
+            ContentItem srcItem = srcRepo.getContent( ).toItem( path );
+            ContentItem dstItem = dstRepo.getContent( ).toItem( path );
+            if (!srcItem.getAsset().exists()){
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_NOT_FOUND, srcRepositoryId, path ), 404 );
+            }
+            if (dstItem.getAsset().exists()) {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_EXISTS_AT_DEST, srcRepositoryId, path ), 400 );
+            }
+            FsStorageUtil.copyAsset( srcItem.getAsset( ), dstItem.getAsset( ), true );
+        }
+        catch ( LayoutException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_LAYOUT_ERROR, e.getMessage() ) );
+        }
+        catch ( IOException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_COPY_ERROR, e.getMessage() ) );
+        }
+        return Response.ok( ).build();
+    }
+
+    private void checkAuthority(final String userName, final String srcRepositoryId, final String dstRepositoryId ) throws ArchivaRestServiceException {
+        User user = null;
+        try
+        {
+            user = securitySystem.getUserManager().findUser( userName );
+        }
+        catch ( UserNotFoundException e )
+        {
+            httpServletResponse.setHeader( "WWW-Authenticate", "Bearer realm=\"archiva\"" );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.USER_NOT_FOUND, userName ), 401 );
+        }
+        catch ( UserManagerException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.USER_MANAGER_ERROR, e.getMessage( ) ) );
+        }
+
+        // check karma on source : read
+        AuthenticationResult authn = new AuthenticationResult( true, userName, null );
+        SecuritySession securitySession = new DefaultSecuritySession( authn, user );
+        try
+        {
+            boolean authz =
+                securitySystem.isAuthorized( securitySession, OPERATION_REPOSITORY_ACCESS,
+                    srcRepositoryId );
+            if ( !authz )
+            {
+                throw new ArchivaRestServiceException(ErrorMessage.of( ErrorKeys.PERMISSION_REPOSITORY_DENIED, srcRepositoryId, OPERATION_REPOSITORY_ACCESS ), 403);
+            }
+        }
+        catch ( AuthorizationException e )
+        {
+            log.error( "Error reading permission: {}", e.getMessage(), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.AUTHORIZATION_ERROR, e.getMessage() ), 403);
+        }
+
+        // check karma on target: write
+        try
+        {
+            boolean authz =
+                securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD,
+                    dstRepositoryId );
+            if ( !authz )
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PERMISSION_REPOSITORY_DENIED, dstRepositoryId, OPERATION_REPOSITORY_UPLOAD ) );
+            }
+        }
+        catch ( AuthorizationException e )
+        {
+            log.error( "Error reading permission: {}", e.getMessage(), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.AUTHORIZATION_ERROR, e.getMessage() ), 403);
+        }
+
+
+    }
+
+    @Override
+    public Response deleteArtifact( String repositoryId, String path ) throws ArchivaRestServiceException
+    {
+
+        return null;
+    }
+
+
+    @Override
+    public Response removeProjectVersion( String repositoryId, String namespace, String projectId, String version ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException
+    {
+        return null;
+    }
+
+    @Override
+    public Response deleteProject( String repositoryId, String namespace, String projectId ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException
+    {
+        return null;
+    }
+
+    @Override
+    public Response deleteNamespace( String repositoryId, String namespace ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException
+    {
+        return null;
+    }
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryGroupService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryGroupService.java
new file mode 100644 (file)
index 0000000..ede4fbb
--- /dev/null
@@ -0,0 +1,328 @@
+package org.apache.archiva.rest.v2.svc;/*
+ * 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.
+ */
+
+/*
+ * 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.components.rest.model.PagedResult;
+import org.apache.archiva.components.rest.util.QueryHelper;
+import org.apache.archiva.configuration.RepositoryGroupConfiguration;
+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.CheckedResult;
+import org.apache.archiva.repository.validation.ValidationError;
+import org.apache.archiva.rest.api.v2.model.MergeConfiguration;
+import org.apache.archiva.rest.api.v2.model.RepositoryGroup;
+import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException;
+import org.apache.archiva.rest.api.v2.svc.ErrorKeys;
+import org.apache.archiva.rest.api.v2.svc.ErrorMessage;
+import org.apache.archiva.rest.api.v2.svc.RepositoryGroupService;
+import org.apache.archiva.rest.api.v2.svc.ValidationException;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+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;
+
+/**
+ * REST V2 Implementation for repository groups.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @see RepositoryGroupService
+ * @since 3.0
+ */
+@Service( "v2.repositoryGroupService#rest" )
+public class DefaultRepositoryGroupService implements RepositoryGroupService
+{
+    private final ConfigurationHandler configurationHandler;
+
+    @Context
+    HttpServletResponse httpServletResponse;
+
+    @Context
+    UriInfo uriInfo;
+
+    final private RepositoryRegistry repositoryRegistry;
+
+
+    private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryGroupService.class );
+    private static final QueryHelper<org.apache.archiva.repository.RepositoryGroup> QUERY_HELPER = new QueryHelper<>( new String[]{"id"} );
+
+    static
+    {
+        QUERY_HELPER.addStringFilter( "id", org.apache.archiva.repository.RepositoryGroup::getId );
+        QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.repository.RepositoryGroup::getId );
+    }
+
+
+    public DefaultRepositoryGroupService( RepositoryRegistry repositoryRegistry, ConfigurationHandler configurationHandler )
+    {
+        this.repositoryRegistry = repositoryRegistry;
+        this.configurationHandler = configurationHandler;
+    }
+
+    @Override
+    public PagedResult<RepositoryGroup> getRepositoriesGroups( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            Predicate<org.apache.archiva.repository.RepositoryGroup> filter = QUERY_HELPER.getQueryFilter( searchTerm );
+            Comparator<org.apache.archiva.repository.RepositoryGroup> ordering = QUERY_HELPER.getComparator( orderBy, QUERY_HELPER.isAscending( order ) );
+            int totalCount = Math.toIntExact( repositoryRegistry.getRepositoryGroups( ).stream( ).filter( filter ).count( ) );
+            List<RepositoryGroup> result = repositoryRegistry.getRepositoryGroups( ).stream( ).filter( filter ).sorted( ordering ).skip( offset ).limit( limit ).map(
+                RepositoryGroup::of
+            ).collect( Collectors.toList( ) );
+            return new PagedResult<>( totalCount, offset, limit, result );
+        }
+        catch ( ArithmeticException e )
+        {
+            log.error( "Could not convert total count: {}", e.getMessage( ) );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) );
+        }
+
+    }
+
+    @Override
+    public RepositoryGroup getRepositoryGroup( String repositoryGroupId ) throws ArchivaRestServiceException
+    {
+        if ( StringUtils.isEmpty( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
+        }
+        org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
+        return RepositoryGroup.of( group );
+    }
+
+    private RepositoryGroupConfiguration toConfig( RepositoryGroup group )
+    {
+        RepositoryGroupConfiguration result = new RepositoryGroupConfiguration( );
+        result.setId( group.getId( ) );
+        result.setName( group.getName() );
+        result.setLocation( group.getLocation( ) );
+        result.setRepositories( group.getRepositories( ) );
+        MergeConfiguration mergeConfig = group.getMergeConfiguration( );
+        if ( mergeConfig != null )
+        {
+            result.setMergedIndexPath( mergeConfig.getMergedIndexPath( ) );
+            result.setMergedIndexTtl( mergeConfig.getMergedIndexTtlMinutes( ) );
+            result.setCronExpression( mergeConfig.getIndexMergeSchedule( ) );
+        }
+        return result;
+    }
+
+    @Override
+    public RepositoryGroup addRepositoryGroup( RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException
+    {
+        final String groupId = repositoryGroup.getId( );
+        if ( StringUtils.isEmpty( groupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_INVALID_ID, groupId ), 422 );
+        }
+        if ( repositoryRegistry.hasRepositoryGroup( groupId ) )
+        {
+            httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( groupId ).build( ).toString( ) );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ID_EXISTS, groupId ), 303 );
+        }
+        try
+        {
+
+            RepositoryGroupConfiguration configuration = toConfig( repositoryGroup );
+            CheckedResult<org.apache.archiva.repository.RepositoryGroup, Map<String, List<ValidationError>>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration );
+            if ( validationResult.isValid( ) )
+            {
+                httpServletResponse.setStatus( 201 );
+                return RepositoryGroup.of( validationResult.getRepository( ) );
+            }
+            else
+            {
+                throw ValidationException.of( validationResult.getResult( ) );
+            }
+        }
+        catch ( RepositoryException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_ADD_FAILED ) );
+        }
+    }
+
+    @Override
+    public RepositoryGroup updateRepositoryGroup( final String repositoryGroupId, final RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException
+    {
+        if ( StringUtils.isEmpty( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
+        }
+        if ( !repositoryRegistry.hasRepositoryGroup( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND ), 404 );
+        }
+        repositoryGroup.setId( repositoryGroupId );
+        try
+        {
+            RepositoryGroupConfiguration configuration = toConfig( repositoryGroup );
+            CheckedResult<org.apache.archiva.repository.RepositoryGroup, Map<String, List<ValidationError>>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration );
+            if ( validationResult.isValid( ) )
+            {
+                httpServletResponse.setStatus( 201 );
+                return RepositoryGroup.of( validationResult.getRepository( ) );
+            }
+            else
+            {
+                throw ValidationException.of( validationResult.getResult( ) );
+            }
+        }
+        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( ) ) );
+
+        }
+    }
+
+    @Override
+    public Response deleteRepositoryGroup( String repositoryGroupId ) throws ArchivaRestServiceException
+    {
+        if ( StringUtils.isEmpty( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
+        }
+        try
+        {
+            org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
+            if ( group == null )
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
+            }
+            repositoryRegistry.removeRepositoryGroup( group );
+            return Response.ok( ).build( );
+        }
+        catch ( RepositoryException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_DELETE_FAILED ) );
+        }
+    }
+
+    @Override
+    public RepositoryGroup addRepositoryToGroup( String repositoryGroupId, String repositoryId ) throws ArchivaRestServiceException
+    {
+        if ( StringUtils.isEmpty( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
+        }
+        if ( StringUtils.isEmpty( repositoryId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, "" ), 404 );
+        }
+        try
+        {
+            org.apache.archiva.repository.RepositoryGroup repositoryGroup = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
+            if ( repositoryGroup == null )
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
+            }
+            if ( !( repositoryGroup instanceof EditableRepositoryGroup ) )
+            {
+                log.error( "This group instance is not editable: {}", repositoryGroupId );
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, "" ), 500 );
+            }
+            EditableRepositoryGroup editableRepositoryGroup = (EditableRepositoryGroup) repositoryGroup;
+            if ( editableRepositoryGroup.getRepositories( ).stream( ).anyMatch( repo -> repositoryId.equals( repo.getId( ) ) ) )
+            {
+                log.info( "Repository {} is already member of group {}", repositoryId, repositoryGroupId );
+                return RepositoryGroup.of( editableRepositoryGroup );
+            }
+            org.apache.archiva.repository.ManagedRepository managedRepo = repositoryRegistry.getManagedRepository( repositoryId );
+            if ( managedRepo == null )
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, "" ), 404 );
+            }
+            editableRepositoryGroup.addRepository( managedRepo );
+            org.apache.archiva.repository.RepositoryGroup newGroup = repositoryRegistry.putRepositoryGroup( editableRepositoryGroup );
+            return RepositoryGroup.of( newGroup );
+        }
+        catch ( RepositoryException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage( ) ), 500 );
+        }
+    }
+
+    @Override
+    public RepositoryGroup deleteRepositoryFromGroup( final String repositoryGroupId, final String repositoryId ) throws ArchivaRestServiceException
+    {
+        if ( StringUtils.isEmpty( repositoryGroupId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, repositoryGroupId ), 404 );
+        }
+        if ( StringUtils.isEmpty( repositoryId ) )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
+        }
+        try
+        {
+            org.apache.archiva.repository.RepositoryGroup repositoryGroup = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
+            if ( repositoryGroup == null )
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
+            }
+            if ( repositoryGroup.getRepositories( ).stream( ).noneMatch( r -> repositoryId.equals( r.getId( ) ) ) )
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
+            }
+            if ( !( repositoryGroup instanceof EditableRepositoryGroup ) )
+            {
+                log.error( "This group instance is not editable: {}", repositoryGroupId );
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, "" ), 500 );
+            }
+            EditableRepositoryGroup editableRepositoryGroup = (EditableRepositoryGroup) repositoryGroup;
+            editableRepositoryGroup.removeRepository( repositoryId );
+            org.apache.archiva.repository.RepositoryGroup newGroup = repositoryRegistry.putRepositoryGroup( editableRepositoryGroup );
+            return RepositoryGroup.of( newGroup );
+        }
+        catch ( RepositoryException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage( ) ), 500 );
+        }
+    }
+
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryService.java
new file mode 100644 (file)
index 0000000..bf1e136
--- /dev/null
@@ -0,0 +1,244 @@
+package org.apache.archiva.rest.v2.svc;
+/*
+ * 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.components.rest.model.PagedResult;
+import org.apache.archiva.components.rest.util.QueryHelper;
+import org.apache.archiva.components.rest.util.RestUtil;
+import org.apache.archiva.metadata.repository.MetadataRepositoryException;
+import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager;
+import org.apache.archiva.repository.RemoteRepository;
+import org.apache.archiva.repository.RepositoryRegistry;
+import org.apache.archiva.repository.scanner.RepositoryScanner;
+import org.apache.archiva.repository.scanner.RepositoryScannerException;
+import org.apache.archiva.rest.api.v2.model.Repository;
+import org.apache.archiva.rest.api.v2.model.RepositoryStatistics;
+import org.apache.archiva.rest.api.v2.model.ScanStatus;
+import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException;
+import org.apache.archiva.rest.api.v2.svc.ErrorKeys;
+import org.apache.archiva.rest.api.v2.svc.ErrorMessage;
+import org.apache.archiva.rest.api.v2.svc.RepositoryService;
+import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexException;
+import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexScheduler;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.inject.Named;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Locale;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ * @since 3.0
+ */
+@Service( "v2.repositoryService#rest" )
+public class DefaultRepositoryService implements RepositoryService
+{
+
+    final
+    RepositoryRegistry repositoryRegistry;
+
+    final
+    RepositoryStatisticsManager repositoryStatisticsManager;
+
+    private final RepositoryTaskAdministration repositoryTaskAdministration;
+
+    private final RepositoryScanner repoScanner;
+
+    private final DownloadRemoteIndexScheduler downloadRemoteIndexScheduler;
+
+    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, DownloadRemoteIndexScheduler downloadRemoteIndexScheduler )
+    {
+        this.repositoryRegistry = repositoryRegistry;
+        this.repositoryStatisticsManager = repositoryStatisticsManager;
+        this.repoScanner = repoScanner;
+        this.repositoryTaskAdministration = repositoryTaskAdministration;
+        this.downloadRemoteIndexScheduler = downloadRemoteIndexScheduler;
+    }
+
+    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
+    {
+        final Locale locale = StringUtils.isNotEmpty( localeString ) ? Locale.forLanguageTag( localeString ) : Locale.getDefault( );
+        boolean isAscending = QUERY_HELPER.isAscending( order );
+        Predicate<org.apache.archiva.repository.Repository> filter = QUERY_HELPER.getQueryFilter( searchTerm );
+        Comparator<org.apache.archiva.repository.Repository> comparator = QUERY_HELPER.getComparator( orderBy, isAscending );
+        try
+        {
+            int totalCount = Math.toIntExact( repositoryRegistry.getRepositories( ).stream( ).filter( filter ).count( ) );
+            return new PagedResult<>( totalCount, offset, limit, repositoryRegistry.getRepositories( ).stream( )
+                .filter( filter ).skip( offset ).limit( limit ).sorted( comparator ).map( repo -> Repository.of( repo, locale ) )
+                .collect( Collectors.toList( ) ) );
+        }
+        catch ( ArithmeticException e )
+        {
+            log.error( "Invalid integer conversion for totalCount" );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) );
+        }
+    }
+
+    @Override
+    public RepositoryStatistics getManagedRepositoryStatistics( String repositoryId ) throws ArchivaRestServiceException
+    {
+        if ( repositoryRegistry.getManagedRepository( repositoryId ) == null )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_MANAGED_NOT_FOUND, repositoryId ), 404 );
+        }
+        try
+        {
+            return RepositoryStatistics.of( repositoryStatisticsManager.getLastStatistics( repositoryId ) );
+        }
+        catch ( MetadataRepositoryException e )
+        {
+            log.error( "Metadata error: {} ", e.getMessage( ), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_METADATA_ERROR, e.getMessage( ) ) );
+        }
+    }
+
+    @Override
+    public Response scheduleRepositoryScan( String repositoryId, boolean fullScan ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            repositoryTaskAdministration.scheduleFullScan( repositoryId );
+            return Response.ok( ).build( );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            handleAdminException( e );
+            return Response.serverError( ).build( );
+        }
+    }
+
+    @Override
+    public RepositoryStatistics scanRepositoryImmediately( String repositoryId ) throws ArchivaRestServiceException
+    {
+        long sinceWhen = RepositoryScanner.FRESH_SCAN;
+        try
+        {
+            return RepositoryStatistics.of( repoScanner.scan( repositoryRegistry.getManagedRepository( repositoryId ), sinceWhen ) );
+        }
+        catch ( RepositoryScannerException e )
+        {
+            log.error( e.getMessage( ), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_SCAN_FAILED, e.getMessage( ) ) );
+        }
+    }
+
+    @Override
+    public ScanStatus getScanStatus( String repositoryId ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            return ScanStatus.of( repositoryTaskAdministration.getCurrentScanStatus( ) );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            handleAdminException( e );
+            return new ScanStatus();
+        }
+    }
+
+    @Override
+    public Response removeScanningTaskFromQueue( String repositoryId ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            repositoryTaskAdministration.cancelTasks( repositoryId );
+            return Response.ok( ).build( );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            handleAdminException( e );
+            return Response.serverError( ).build( );
+        }
+    }
+
+
+    @Override
+    public Response scheduleDownloadRemoteIndex( String repositoryId, boolean immediately, boolean full,
+                                                 UriInfo uriInfo ) throws ArchivaRestServiceException
+    {
+        boolean immediateSet = RestUtil.isFlagSet( uriInfo, "immediate" );
+        boolean fullSet = RestUtil.isFlagSet( uriInfo, "full" );
+        RemoteRepository repo = repositoryRegistry.getRemoteRepository( repositoryId );
+        if (repo==null) {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_NOT_FOUND, repositoryId ), 404 );
+        }
+        try
+        {
+            downloadRemoteIndexScheduler.scheduleDownloadRemote( repositoryId, immediateSet, fullSet );
+            return Response.ok( ).build( );
+        }
+        catch ( DownloadRemoteIndexException e )
+        {
+            log.error( "Could not schedule index download for repository {}: {}", repositoryId, e.getMessage(), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED, e.getMessage( ) ) );
+        }
+    }
+
+
+
+    @Override
+    public List<String> getRunningRemoteDownloads( )
+    {
+        return downloadRemoteIndexScheduler.getRunningRemoteDownloadIds( );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultSecurityConfigurationService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultSecurityConfigurationService.java
new file mode 100644 (file)
index 0000000..6e6a157
--- /dev/null
@@ -0,0 +1,677 @@
+package org.apache.archiva.rest.v2.svc;/*
+ * 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.
+ */
+
+/*
+ * 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.RedbackRuntimeConfiguration;
+import org.apache.archiva.admin.model.runtime.RedbackRuntimeConfigurationAdmin;
+import org.apache.archiva.components.rest.model.PagedResult;
+import org.apache.archiva.components.rest.model.PropertyEntry;
+import org.apache.archiva.components.rest.util.QueryHelper;
+import org.apache.archiva.redback.authentication.Authenticator;
+import org.apache.archiva.redback.common.ldap.connection.LdapConnection;
+import org.apache.archiva.redback.common.ldap.connection.LdapConnectionConfiguration;
+import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory;
+import org.apache.archiva.redback.common.ldap.connection.LdapException;
+import org.apache.archiva.redback.common.ldap.user.LdapUserMapper;
+import org.apache.archiva.redback.policy.CookieSettings;
+import org.apache.archiva.redback.policy.PasswordRule;
+import org.apache.archiva.redback.rbac.RBACManager;
+import org.apache.archiva.redback.role.RoleManager;
+import org.apache.archiva.redback.users.UserManager;
+import org.apache.archiva.rest.api.v2.model.BeanInformation;
+import org.apache.archiva.rest.api.v2.model.CacheConfiguration;
+import org.apache.archiva.rest.api.v2.model.LdapConfiguration;
+import org.apache.archiva.rest.api.v2.model.SecurityConfiguration;
+import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException;
+import org.apache.archiva.rest.api.v2.svc.ErrorKeys;
+import org.apache.archiva.rest.api.v2.svc.ErrorMessage;
+import org.apache.archiva.rest.api.v2.svc.SecurityConfigurationService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.naming.AuthenticationException;
+import javax.naming.AuthenticationNotSupportedException;
+import javax.naming.CommunicationException;
+import javax.naming.InvalidNameException;
+import javax.naming.NamingException;
+import javax.naming.NoPermissionException;
+import javax.naming.ServiceUnavailableException;
+import javax.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static org.apache.archiva.rest.api.v2.svc.ErrorKeys.INVALID_RESULT_SET_ERROR;
+import static org.apache.archiva.rest.api.v2.svc.ErrorKeys.REPOSITORY_ADMIN_ERROR;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Service( "v2.defaultSecurityConfigurationService" )
+public class DefaultSecurityConfigurationService implements SecurityConfigurationService
+{
+    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 final List<String> availableContextProviders = new ArrayList<>( );
+
+    private static final QueryHelper<PropertyEntry> PROP_QUERY_HELPER = new QueryHelper<>( new String[]{"key"} );
+
+    static
+    {
+        PROP_QUERY_HELPER.addStringFilter( "key", PropertyEntry::getKey );
+        PROP_QUERY_HELPER.addStringFilter( "value", PropertyEntry::getValue );
+        PROP_QUERY_HELPER.addNullsafeFieldComparator( "key", PropertyEntry::getKey );
+        PROP_QUERY_HELPER.addNullsafeFieldComparator( "value", PropertyEntry::getValue );
+
+    }
+
+    private ResourceBundle bundle;
+
+
+    @Inject
+    private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin;
+
+    @Inject
+    private ApplicationContext applicationContext;
+
+    @Inject
+    @Named( value = "userManager#default" )
+    private UserManager userManager;
+
+    @Inject
+    @Named( value = "rbacManager#default" )
+    private RBACManager rbacManager;
+
+    @Inject
+    private RoleManager roleManager;
+
+    @Inject
+    @Named( value = "ldapConnectionFactory#configurable" )
+    private LdapConnectionFactory ldapConnectionFactory;
+
+    @Inject
+    private LdapUserMapper ldapUserMapper;
+
+
+    @PostConstruct
+    void init( )
+    {
+        bundle = ResourceBundle.getBundle( "org.apache.archiva.rest.RestBundle" );
+        for (String ldapClass : KNOWN_LDAP_CONTEXT_PROVIDERS) {
+            if (isContextFactoryAvailable( ldapClass )) {
+                availableContextProviders.add( ldapClass );
+            }
+        }
+    }
+
+    @Override
+    public SecurityConfiguration getConfiguration( ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
+                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
+
+            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
+
+            return SecurityConfiguration.ofRedbackConfiguration( redbackRuntimeConfiguration );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
+        }
+    }
+
+    private void updateConfig( SecurityConfiguration newConfig, RedbackRuntimeConfiguration rbConfig )
+    {
+        rbConfig.setUserManagerImpls( newConfig.getActiveUserManagers( ) );
+        rbConfig.setRbacManagerImpls( newConfig.getActiveRbacManagers( ) );
+        rbConfig.setUseUsersCache( newConfig.isUserCacheEnabled( ) );
+        Map<String, String> props = rbConfig.getConfigurationProperties( );
+        for ( Map.Entry<String, String> newProp : newConfig.getProperties( ).entrySet( ) )
+        {
+            props.put( newProp.getKey( ), newProp.getValue( ) );
+        }
+    }
+
+    private void updateConfig( LdapConfiguration newConfig, RedbackRuntimeConfiguration rbConfig )
+    {
+        org.apache.archiva.admin.model.beans.LdapConfiguration ldapConfig = rbConfig.getLdapConfiguration( );
+        ldapConfig.setBaseDn( newConfig.getBaseDn( ) );
+        ldapConfig.setAuthenticationMethod( newConfig.getAuthenticationMethod( ) );
+        ldapConfig.setBindAuthenticatorEnabled( newConfig.isBindAuthenticatorEnabled( ) );
+        ldapConfig.setBindDn( newConfig.getBindDn( ) );
+        ldapConfig.setSsl( newConfig.isSslEnabled( ) );
+        ldapConfig.setBaseGroupsDn( newConfig.getGroupsBaseDn( ) );
+        ldapConfig.setHostName( newConfig.getHostName( ) );
+        ldapConfig.setPort( newConfig.getPort( ) );
+        ldapConfig.setPassword( newConfig.getBindPassword( ) );
+        ldapConfig.setUseRoleNameAsGroup( newConfig.isUseRoleNameAsGroup( ) );
+        ldapConfig.setWritable( newConfig.isWritable( ) );
+        ldapConfig.setContextFactory( newConfig.getContextFactory( ) );
+
+        Map<String, String> props = ldapConfig.getExtraProperties( );
+        for ( Map.Entry<String, String> newProp : newConfig.getProperties( ).entrySet( ) )
+        {
+            props.put( newProp.getKey( ), newProp.getValue( ) );
+        }
+    }
+
+    private void updateConfig( CacheConfiguration newConfig, RedbackRuntimeConfiguration rbConfig )
+    {
+        org.apache.archiva.admin.model.beans.CacheConfiguration cacheConfig = rbConfig.getUsersCacheConfiguration( );
+        cacheConfig.setMaxElementsInMemory( newConfig.getMaxEntriesInMemory( ) );
+        cacheConfig.setMaxElementsOnDisk( newConfig.getMaxEntriesOnDisk( ) );
+        cacheConfig.setTimeToLiveSeconds( newConfig.getTimeToLiveSeconds( ) );
+        cacheConfig.setTimeToIdleSeconds( newConfig.getTimeToIdleSeconds( ) );
+    }
+
+    @Override
+    public SecurityConfiguration updateConfiguration( SecurityConfiguration newConfiguration ) throws ArchivaRestServiceException
+    {
+        if ( newConfiguration == null )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 );
+        }
+        try
+        {
+            RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
+            boolean userManagerChanged = !CollectionUtils.isEqualCollection( newConfiguration.getActiveUserManagers( ), conf.getUserManagerImpls( ) );
+            boolean rbacManagerChanged = !CollectionUtils.isEqualCollection( newConfiguration.getActiveRbacManagers( ), conf.getRbacManagerImpls( ) );
+
+            boolean ldapConfigured = newConfiguration.getActiveUserManagers( ).stream( ).anyMatch( um -> um.contains( "ldap" ) );
+            if ( !ldapConfigured )
+            {
+                ldapConfigured= newConfiguration.getActiveRbacManagers( ).stream( ).anyMatch( um -> um.contains( "ldap" ) );
+            }
+
+            updateConfig( newConfiguration, conf );
+            redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( conf );
+
+            if ( userManagerChanged )
+            {
+                log.info( "user managerImpls changed to {} so reload it",
+                    newConfiguration.getActiveUserManagers( ) );
+                userManager.initialize( );
+            }
+
+            if ( rbacManagerChanged )
+            {
+                log.info( "rbac manager changed to {} so reload it",
+                    newConfiguration.getActiveRbacManagers( ) );
+                rbacManager.initialize( );
+                roleManager.initialize( );
+            }
+
+            if ( ldapConfigured )
+            {
+                try
+                {
+                    ldapConnectionFactory.initialize( );
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Could not initialize LDAP connection factory: {}", e.getMessage( ) );
+                    throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_CF_INIT_FAILED, e.getMessage( ) ) );
+                }
+            }
+            Collection<PasswordRule> passwordRules = applicationContext.getBeansOfType( PasswordRule.class ).values( );
+
+            for ( PasswordRule passwordRule : passwordRules )
+            {
+                passwordRule.initialize( );
+            }
+
+            Collection<CookieSettings> cookieSettingsList =
+                applicationContext.getBeansOfType( CookieSettings.class ).values( );
+
+            for ( CookieSettings cookieSettings : cookieSettingsList )
+            {
+                cookieSettings.initialize( );
+            }
+
+            Collection<Authenticator> authenticators =
+                applicationContext.getBeansOfType( Authenticator.class ).values( );
+
+            for ( Authenticator authenticator : authenticators )
+            {
+                try
+                {
+                    log.debug( "Initializing authenticatior " + authenticator.getId( ) );
+                    authenticator.initialize( );
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Initialization of authenticator failed " + authenticator.getId( ), e );
+                }
+            }
+
+            if ( ldapConfigured )
+            {
+                try
+                {
+                    ldapUserMapper.initialize( );
+                }
+                catch ( Exception e )
+                {
+                    throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_USER_MAPPER_INIT_FAILED, e.getMessage( ) ) );
+                }
+            }
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+        }
+        try
+        {
+            return SecurityConfiguration.ofRedbackConfiguration( redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ) );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            log.error( "Error while retrieve updated configuration: {}", e.getMessage( ) );
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+        }
+    }
+
+    @Override
+    public PagedResult<PropertyEntry> getConfigurationProperties( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
+                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
+
+            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
+
+            boolean ascending = PROP_QUERY_HELPER.isAscending( order );
+            Predicate<PropertyEntry> filter = PROP_QUERY_HELPER.getQueryFilter( searchTerm );
+            Comparator<PropertyEntry> comparator = PROP_QUERY_HELPER.getComparator( orderBy, ascending );
+            Map<String, String> props = redbackRuntimeConfiguration.getConfigurationProperties( );
+            int totalCount = Math.toIntExact( props.entrySet( ).stream( ).map(
+                entry -> new PropertyEntry( entry.getKey( ), entry.getValue( ) )
+            ).filter( filter ).count( ) );
+            List<PropertyEntry> result = props.entrySet( ).stream( ).map(
+                entry -> new PropertyEntry( entry.getKey( ), entry.getValue( ) )
+            ).filter( filter )
+                .sorted( comparator )
+                .skip( offset ).limit( limit )
+                .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!" );
+            throw new ArchivaRestServiceException( ErrorMessage.of( INVALID_RESULT_SET_ERROR ) );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
+        }
+    }
+
+    @Override
+    public PropertyEntry getConfigurationProperty( String propertyName ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
+            if ( conf.getConfigurationProperties( ).containsKey( propertyName ) )
+            {
+                String value = conf.getConfigurationProperties( ).get( propertyName );
+                return new PropertyEntry( propertyName, value );
+            }
+            else
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PROPERTY_NOT_FOUND ), 404 );
+            }
+
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+        }
+
+    }
+
+    @Override
+    public Response updateConfigurationProperty( String propertyName, PropertyEntry propertyValue ) throws ArchivaRestServiceException
+    {
+        if ( propertyValue == null )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 );
+        }
+        try
+        {
+            RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
+            if ( conf.getConfigurationProperties( ).containsKey( propertyName ) )
+            {
+                conf.getConfigurationProperties( ).put( propertyName, propertyValue.getValue( ) );
+                redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( conf );
+                return Response.ok( ).build( );
+            }
+            else
+            {
+                throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PROPERTY_NOT_FOUND ), 404 );
+            }
+
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+        }
+    }
+
+    @Override
+    public LdapConfiguration getLdapConfiguration( ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
+                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
+
+            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
+
+            LdapConfiguration ldapConfig = LdapConfiguration.of( redbackRuntimeConfiguration.getLdapConfiguration( ) );
+            ldapConfig.setAvailableContextFactories( availableContextProviders );
+            return ldapConfig;
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
+        }
+
+    }
+
+    @Override
+    public LdapConfiguration updateLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
+                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
+
+            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
+
+            updateConfig( configuration, redbackRuntimeConfiguration );
+
+            redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration );
+            ldapConnectionFactory.initialize( );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
+        }
+
+        try
+        {
+            return LdapConfiguration.of( redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ).getLdapConfiguration() );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            log.error( "Error while retrieve updated configuration: {}", e.getMessage( ) );
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+        }
+
+    }
+
+    static Properties toProperties( Map<String, String> values )
+    {
+        Properties result = new Properties( );
+        for ( Map.Entry<String, String> entry : values.entrySet( ) )
+        {
+            result.setProperty( entry.getKey( ), entry.getValue( ) );
+        }
+        return result;
+    }
+
+    private static boolean isContextFactoryAvailable( final String factoryClass)
+    {
+        try
+        {
+            return Thread.currentThread().getContextClassLoader().loadClass( factoryClass )
+                != null;
+        }
+        catch ( ClassNotFoundException e )
+        {
+            return false;
+        }
+    }
+
+
+    @Override
+    public Response verifyLdapConfiguration( LdapConfiguration ldapConfiguration ) throws ArchivaRestServiceException
+    {
+        LdapConnection ldapConnection = null;
+        try
+        {
+            LdapConnectionConfiguration ldapConnectionConfiguration =
+                new LdapConnectionConfiguration( ldapConfiguration.getHostName( ), ldapConfiguration.getPort( ),
+                    ldapConfiguration.getBaseDn( ), ldapConfiguration.getContextFactory( ),
+                    ldapConfiguration.getBindDn( ), ldapConfiguration.getBindPassword( ),
+                    ldapConfiguration.getAuthenticationMethod( ),
+                    toProperties( ldapConfiguration.getProperties( ) ) );
+            ldapConnectionConfiguration.setSsl( ldapConfiguration.isSslEnabled( ) );
+
+            ldapConnection = ldapConnectionFactory.getConnection( ldapConnectionConfiguration );
+        }
+        catch ( InvalidNameException e )
+        {
+            log.warn( "LDAP connection check failed with invalid name : {}", e.getMessage( ), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_INVALID_NAME, e.getMessage( ) ), 400 );
+        }
+        catch ( LdapException e )
+        {
+            handleLdapException( e );
+        }
+        finally
+        {
+            if ( ldapConnection != null )
+            {
+                try
+                {
+                    ldapConnection.close( );
+                }
+                catch ( NamingException e )
+                {
+                    log.error( "Could not close connection: {}", e.getMessage( ) );
+                }
+            }
+            ldapConnection = null;
+        }
+
+        try
+        {
+            // verify groups dn value too
+
+            LdapConnectionConfiguration ldapConnectionConfiguration = new LdapConnectionConfiguration( ldapConfiguration.getHostName( ), ldapConfiguration.getPort( ),
+                ldapConfiguration.getGroupsBaseDn( ),
+                ldapConfiguration.getContextFactory( ), ldapConfiguration.getBindDn( ),
+                ldapConfiguration.getBindPassword( ),
+                ldapConfiguration.getAuthenticationMethod( ),
+                toProperties( ldapConfiguration.getProperties( ) ) );
+
+            ldapConnectionConfiguration.setSsl( ldapConfiguration.isSslEnabled( ) );
+
+            ldapConnection = ldapConnectionFactory.getConnection( ldapConnectionConfiguration );
+        }
+        catch ( InvalidNameException e )
+        {
+            log.warn( "LDAP connection check failed with invalid name : {}", e.getMessage( ), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_INVALID_NAME, e.getMessage( ) ), 400 );
+        }
+        catch ( LdapException e )
+        {
+            handleLdapException( e );
+        }
+        finally
+        {
+            if ( ldapConnection != null )
+            {
+                try
+                {
+                    ldapConnection.close( );
+                }
+                catch ( NamingException e )
+                {
+                    log.error( "Could not close connection: {}", e.getMessage( ), e );
+                }
+            }
+        }
+
+        return Response.ok( ).build( );
+    }
+
+    private void handleLdapException( LdapException e ) throws ArchivaRestServiceException
+    {
+        Throwable rootCause = e.getRootCause( );
+        if ( rootCause instanceof CommunicationException )
+        {
+            log.warn( "LDAP connection check failed with CommunicationException: {}", e.getMessage( ), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_COMMUNICATION_ERROR, e.getMessage( ) ), 400 );
+        } else if (rootCause instanceof ServiceUnavailableException ) {
+            log.warn( "LDAP connection check failed with ServiceUnavailableException: {}", e.getMessage( ), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_UNAVAILABLE, e.getMessage( ) ), 400 );
+        } else if (rootCause instanceof AuthenticationException ) {
+            log.warn( "LDAP connection check failed with AuthenticationException: {}", e.getMessage( ), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_AUTHENTICATION_FAILED, e.getMessage( ) ), 400 );
+        } else if (rootCause instanceof AuthenticationNotSupportedException ) {
+            log.warn( "LDAP connection check failed with AuthenticationNotSupportedException: {}", e.getMessage( ), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_AUTHENTICATION_NOT_SUPPORTED, e.getMessage( ) ), 400 );
+        } else if (rootCause instanceof NoPermissionException ) {
+            log.warn( "LDAP connection check failed with NoPermissionException: {}", e.getMessage( ), e );
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_NO_PERMISSION, e.getMessage( ) ), 400 );
+        }
+        log.warn( "LDAP connection check failed: {} - {}", e.getClass().getName(), e.getMessage( ), e );
+        throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_GENERIC_ERROR, e.getMessage( ) ), 400 );
+    }
+
+    @Override
+    public CacheConfiguration getCacheConfiguration( ) throws ArchivaRestServiceException
+    {
+        try
+        {
+            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
+                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
+
+            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
+
+            return CacheConfiguration.of( redbackRuntimeConfiguration.getUsersCacheConfiguration( ) );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
+        }
+
+    }
+
+    @Override
+    public CacheConfiguration updateCacheConfiguration( CacheConfiguration cacheConfiguration ) throws ArchivaRestServiceException
+    {
+        if ( cacheConfiguration == null )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 );
+        }
+        try
+        {
+            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
+                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
+
+            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
+            updateConfig( cacheConfiguration, redbackRuntimeConfiguration );
+            redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration );
+            return getCacheConfiguration( );
+        }
+        catch ( RepositoryAdminException e )
+        {
+            throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
+        }
+    }
+
+    @Override
+    public List<BeanInformation> getAvailableUserManagers( )
+    {
+        Map<String, UserManager> beans = applicationContext.getBeansOfType( UserManager.class );
+
+        if ( beans.isEmpty( ) )
+        {
+            return Collections.emptyList( );
+        }
+
+        return beans.entrySet( ).stream( )
+            .filter( entry -> entry.getValue( ).isFinalImplementation( ) )
+            .map( ( Map.Entry<String, UserManager> entry ) -> {
+                UserManager um = entry.getValue( );
+                String id = StringUtils.substringAfter( entry.getKey( ), "#" );
+                String displayName = bundle.getString( "user_manager." + id + ".display_name" );
+                String description = bundle.getString( "user_manager." + id + ".description" );
+                return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, um.getDescriptionKey( ), description, um.isReadOnly( ) );
+            } ).collect( Collectors.toList( ) );
+    }
+
+    @Override
+    public List<BeanInformation> getAvailableRbacManagers( )
+    {
+        Map<String, RBACManager> beans = applicationContext.getBeansOfType( RBACManager.class );
+
+        if ( beans.isEmpty( ) )
+        {
+            return Collections.emptyList( );
+        }
+
+        return beans.entrySet( ).stream( )
+            .filter( entry -> entry.getValue( ).isFinalImplementation( ) )
+            .map( ( Map.Entry<String, RBACManager> entry ) -> {
+                RBACManager rm = entry.getValue( );
+                String id = StringUtils.substringAfter( entry.getKey( ), "#" );
+                String displayName = bundle.getString( "rbac_manager." + id + ".display_name" );
+                String description = bundle.getString( "rbac_manager." + id + ".description" );
+                return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, rm.getDescriptionKey( ), description, rm.isReadOnly( ) );
+            } ).collect( Collectors.toList( ) );
+    }
+}
index 46dbc499a45e3cde9399732970ae227dfbf1f37c..6f5f1fc1fbf06471d5ef05bd48b6d953036ad6fe 100644 (file)
@@ -34,7 +34,7 @@
 
   <context:annotation-config/>
   <context:component-scan
-      base-package="org.apache.archiva.rest.services,org.apache.archiva.redback.rest.services"/>
+      base-package="org.apache.archiva.rest.services,org.apache.archiva.redback.rest.services,org.apache.archiva.rest.v2"/>
 
   <!-- CXF OpenApiFeature -->
   <bean id="archivaOpenApiFeature" class="org.apache.cxf.jaxrs.openapi.OpenApiFeature">
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/AbstractNativeRestServices.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/AbstractNativeRestServices.java
deleted file mode 100644 (file)
index 9a9b7e8..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-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 com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.PropertyNamingStrategy;
-import io.restassured.RestAssured;
-import io.restassured.builder.RequestSpecBuilder;
-import io.restassured.config.ObjectMapperConfig;
-import io.restassured.config.RestAssuredConfig;
-import io.restassured.path.json.mapper.factory.Jackson2ObjectMapperFactory;
-import io.restassured.response.Response;
-import io.restassured.specification.RequestSpecification;
-import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants;
-import org.apache.archiva.redback.rest.services.BaseSetup;
-import org.apache.archiva.redback.role.RoleManager;
-import org.apache.archiva.redback.role.RoleManagerException;
-import org.apache.archiva.redback.users.User;
-import org.apache.archiva.redback.users.UserManager;
-import org.apache.archiva.redback.users.UserManagerException;
-import org.apache.archiva.redback.users.UserNotFoundException;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.SystemUtils;
-import org.apache.cxf.transport.servlet.CXFServlet;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.session.SessionHandler;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.junit.jupiter.api.Tag;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.context.ContextLoaderListener;
-
-import java.lang.reflect.Type;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.time.LocalTime;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static io.restassured.RestAssured.*;
-import static io.restassured.http.ContentType.JSON;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-/**
- * Native REST tests do not use the JAX-RS client and can be used with a remote
- * REST API service. The tests
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Tag( "rest-native" )
-@Tag( "rest-v2" )
-public abstract class AbstractNativeRestServices
-{
-    private AtomicReference<Path> projectDir = new AtomicReference<>();
-    private AtomicReference<Path> appServerBase = new AtomicReference<>( );
-    private AtomicReference<Path> basePath = new AtomicReference<>( );
-
-    public static final int STOPPED = 0;
-    public static final int STOPPING = 1;
-    public static final int STARTING = 2;
-    public static final int STARTED = 3;
-    public static final int ERROR = 4;
-    private final boolean startServer;
-    private final String serverPort;
-    private final String baseUri;
-
-    private RequestSpecification requestSpec;
-    protected Logger log = LoggerFactory.getLogger( getClass( ) );
-
-    private static AtomicReference<Server> server = new AtomicReference<>( );
-    private static AtomicReference<ServerConnector> serverConnector = new AtomicReference<>( );
-    private static AtomicInteger serverStarted = new AtomicInteger( STOPPED );
-    private UserManager userManager;
-    private RoleManager roleManager;
-
-    private final boolean remoteService;
-
-    private String adminToken;
-    private String adminRefreshToken;
-
-
-    public AbstractNativeRestServices( )
-    {
-        this.startServer = BaseSetup.startServer( );
-        this.serverPort = BaseSetup.getServerPort( );
-        this.baseUri = BaseSetup.getBaseUri( );
-
-        if ( startServer )
-        {
-            this.remoteService = false;
-        } else {
-            this.remoteService = true;
-        }
-    }
-
-    protected abstract String getServicePath( );
-
-    protected String getSpringConfigLocation( )
-    {
-        return "classpath*:META-INF/spring-context.xml,classpath:META-INF/spring-context-native-test.xml";
-    }
-
-    protected RequestSpecification getRequestSpec( )
-    {
-        return this.requestSpec;
-    }
-
-    protected String getContextRoot( )
-    {
-        return "/api";
-    }
-
-
-    protected String getServiceBasePath( )
-    {
-        return "/v2/archiva";
-    }
-
-    protected String getRedbackServiceBasePath( )
-    {
-        return "/v2/redback";
-    }
-
-
-    protected String getBasePath( )
-    {
-        return new StringBuilder( )
-            .append( getContextRoot( ) )
-            .append( getServiceBasePath( ) )
-            .append( getServicePath( ) ).toString( );
-    }
-
-    /**
-     * Returns the server that was started, or null if not initialized before.
-     *
-     * @return
-     */
-    public Server getServer( )
-    {
-        return this.server.get( );
-    }
-
-    public int getServerPort( )
-    {
-        ServerConnector connector = serverConnector.get( );
-        if ( connector != null )
-        {
-            return connector.getLocalPort( );
-        }
-        else
-        {
-            return 0;
-        }
-    }
-
-    /**
-     * Returns true, if the server does exist and is running.
-     *
-     * @return true, if server does exist and is running.
-     */
-    public boolean isServerRunning( )
-    {
-        return serverStarted.get( ) == STARTED && this.server.get( ) != null && this.server.get( ).isRunning( );
-    }
-
-    private UserManager getUserManager( )
-    {
-        if ( this.userManager == null )
-        {
-            UserManager userManager = ContextLoaderListener.getCurrentWebApplicationContext( )
-                .getBean( "userManager#default", UserManager.class );
-            assertNotNull( userManager );
-            this.userManager = userManager;
-        }
-        return this.userManager;
-    }
-
-    private RoleManager getRoleManager( )
-    {
-        if ( this.roleManager == null )
-        {
-            RoleManager roleManager = ContextLoaderListener.getCurrentWebApplicationContext( )
-                .getBean( "roleManager", RoleManager.class );
-            assertNotNull( roleManager );
-            this.roleManager = roleManager;
-        }
-        return this.roleManager;
-    }
-
-    protected String getAdminPwd( )
-    {
-        return BaseSetup.getAdminPwd( );
-    }
-
-    protected String getAdminUser( )
-    {
-        return RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME;
-    }
-
-    private void setupAdminUser( ) throws UserManagerException, RoleManagerException
-    {
-
-        UserManager um = getUserManager( );
-
-        User adminUser = null;
-        try
-        {
-            adminUser = um.findUser( getAdminUser( ) );
-        }
-        catch ( UserNotFoundException e )
-        {
-            // ignore
-        }
-        adminUser = um.createUser( getAdminUser( ), "Administrator", "admin@local.home" );
-        adminUser.setUsername( getAdminUser( ) );
-        adminUser.setPassword( getAdminPwd( ) );
-        adminUser.setFullName( "the admin user" );
-        adminUser.setEmail( "toto@toto.fr" );
-        adminUser.setPermanent( true );
-        adminUser.setValidated( true );
-        adminUser.setLocked( false );
-        adminUser.setPasswordChangeRequired( false );
-        if ( adminUser == null )
-        {
-            um.addUser( adminUser );
-        }
-        else
-        {
-            um.updateUser( adminUser, false );
-        }
-        getRoleManager( ).assignRole( "system-administrator", adminUser.getUsername( ) );
-    }
-
-    protected Path getProjectDirectory() {
-        if ( projectDir.get()==null) {
-            String propVal = System.getProperty("mvn.project.base.dir");
-            Path newVal;
-            if (StringUtils.isEmpty(propVal)) {
-                newVal = Paths.get("").toAbsolutePath();
-            } else {
-                newVal = Paths.get(propVal).toAbsolutePath();
-            }
-            projectDir.compareAndSet(null, newVal);
-        }
-        return projectDir.get();
-    }
-
-    public Path getBasedir()
-    {
-        if (basePath.get()==null) {
-            String baseDir = System.getProperty( "basedir" );
-            final Path baseDirPath;
-            if (StringUtils.isNotEmpty( baseDir ))  {
-                baseDirPath = Paths.get( baseDir );
-            } else {
-                baseDirPath = getProjectDirectory( );
-            }
-            basePath.compareAndSet( null, baseDirPath );
-        }
-        return basePath.get( );
-    }
-
-    Path getAppserverBase() {
-        if (appServerBase.get()==null) {
-            String basePath = System.getProperty( "appserver.base" );
-            final Path appserverPath;
-            if (StringUtils.isNotEmpty( basePath )) {
-                appserverPath = Paths.get( basePath ).toAbsolutePath( );
-            } else {
-                appserverPath = getBasedir( ).resolve( "target" ).resolve( "appserver-base-" + LocalTime.now( ).toSecondOfDay( ) );
-            }
-            appServerBase.compareAndSet( null, appserverPath );
-        }
-        return appServerBase.get();
-    }
-
-    private void removeAppsubFolder( Path appServerBase, String folder )
-        throws Exception
-    {
-        Path directory = appServerBase.resolve( folder );
-        if ( Files.exists(directory) )
-        {
-            org.apache.archiva.common.utils.FileUtils.deleteDirectory( directory );
-        }
-    }
-
-    public void startServer( )
-        throws Exception
-    {
-        if ( serverStarted.compareAndSet( STOPPED, STARTING ) )
-        {
-            try
-            {
-                log.info( "Starting server" );
-                Path appServerBase = getAppserverBase( );
-
-                removeAppsubFolder(appServerBase, "jcr");
-                removeAppsubFolder(appServerBase, "conf");
-                removeAppsubFolder(appServerBase, "data");
-
-
-                Server myServer = new Server( );
-                this.server.set( myServer );
-                this.serverConnector.set( new ServerConnector( myServer, new HttpConnectionFactory( ) ) );
-                myServer.addConnector( serverConnector.get( ) );
-
-                ServletHolder servletHolder = new ServletHolder( new CXFServlet( ) );
-                ServletContextHandler context = new ServletContextHandler( ServletContextHandler.SESSIONS );
-                context.setResourceBase( SystemUtils.JAVA_IO_TMPDIR );
-                context.setSessionHandler( new SessionHandler( ) );
-                context.addServlet( servletHolder, getContextRoot( ) + "/*" );
-                context.setInitParameter( "contextConfigLocation", getSpringConfigLocation( ) );
-                context.addEventListener( new ContextLoaderListener( ) );
-
-                getServer( ).setHandler( context );
-                getServer( ).start( );
-
-                if ( log.isDebugEnabled( ) )
-                {
-                    log.debug( "Jetty dump: {}", getServer( ).dump( ) );
-                }
-
-                setupAdminUser( );
-                log.info( "Started server on port {}", getServerPort( ) );
-                serverStarted.set( STARTED );
-            }
-            finally
-            {
-                // In case, if the last statement was not reached
-                serverStarted.compareAndSet( STARTING, ERROR );
-            }
-        }
-
-    }
-
-    public void stopServer( )
-        throws Exception
-    {
-        if ( this.serverStarted.compareAndSet( STARTED, STOPPING ) )
-        {
-            try
-            {
-                final Server myServer = getServer( );
-                if ( myServer != null )
-                {
-                    log.info( "Stopping server" );
-                    myServer.stop( );
-                }
-                serverStarted.set( STOPPED );
-            }
-            finally
-            {
-                serverStarted.compareAndSet( STOPPING, ERROR );
-            }
-        }
-        else
-        {
-            log.error( "Server is not in STARTED state!" );
-        }
-    }
-
-
-    protected void setupNative( ) throws Exception
-    {
-        if ( this.startServer )
-        {
-            startServer( );
-        }
-
-        if ( StringUtils.isNotEmpty( serverPort ) )
-        {
-            RestAssured.port = Integer.parseInt( serverPort );
-        }
-        else
-        {
-            RestAssured.port = getServerPort( );
-        }
-        if ( StringUtils.isNotEmpty( baseUri ) )
-        {
-            RestAssured.baseURI = baseUri;
-        }
-        else
-        {
-            RestAssured.baseURI = "http://localhost";
-        }
-        String basePath = getBasePath( );
-        this.requestSpec = getRequestSpecBuilder( ).build( );
-        RestAssured.basePath = basePath;
-        RestAssured.config = RestAssuredConfig.config().objectMapperConfig(new ObjectMapperConfig().jackson2ObjectMapperFactory(
-            ( cls, charset ) -> {
-                ObjectMapper om = new ObjectMapper().findAndRegisterModules();
-                om.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
-                om.setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE );
-                return om;
-            }
-        ));
-    }
-
-    protected RequestSpecBuilder getRequestSpecBuilder( ) {
-        return getRequestSpecBuilder( null );
-    }
-
-    protected RequestSpecBuilder getRequestSpecBuilder( String basePath )
-    {
-        String myBasePath = basePath == null ? getBasePath( ) : basePath;
-        return new RequestSpecBuilder( ).setBaseUri( baseURI )
-            .setPort( port )
-            .setBasePath( myBasePath )
-            .addHeader( "Origin", RestAssured.baseURI + ":" + RestAssured.port );
-    }
-
-    protected RequestSpecBuilder getAuthRequestSpecBuilder( )
-    {
-        return new RequestSpecBuilder( ).setBaseUri( baseURI )
-            .setPort( port )
-            .setBasePath( new StringBuilder( )
-                .append( getContextRoot( ) )
-                .append( getRedbackServiceBasePath() ).append("/auth").toString() )
-            .addHeader( "Origin", RestAssured.baseURI + ":" + RestAssured.port );
-    }
-
-    protected RequestSpecification getRequestSpec( String bearerToken )
-    {
-        return getRequestSpecBuilder( ).addHeader( "Authorization", "Bearer " + bearerToken ).build( );
-    }
-
-    protected RequestSpecification getRequestSpec( String bearerToken, String path)
-    {
-        return getRequestSpecBuilder( path  ).addHeader( "Authorization", "Bearer " + bearerToken ).build( );
-    }
-
-    protected void shutdownNative( ) throws Exception
-    {
-        if (startServer)
-        {
-            stopServer( );
-        }
-    }
-
-    protected org.apache.archiva.redback.rest.api.model.User addRemoteUser(String userid, String password, String fullName, String mail) {
-
-        return null;
-    }
-
-    protected void initAdminToken() {
-        Map<String, Object> jsonAsMap = new HashMap<>();
-        jsonAsMap.put( "grant_type", "authorization_code" );
-        jsonAsMap.put("user_id", getAdminUser());
-        jsonAsMap.put("password", getAdminPwd() );
-        Response result = given( ).spec( getAuthRequestSpecBuilder().build() )
-            .contentType( JSON )
-            .body( jsonAsMap )
-            .when( ).post( "/authenticate").then( ).statusCode( 200 )
-            .extract( ).response( );
-        this.adminToken = result.body( ).jsonPath( ).getString( "access_token" );
-        this.adminRefreshToken = result.body( ).jsonPath( ).getString( "refresh_token" );
-    }
-
-    protected String getUserToken(String userId, String password) {
-        Map<String, Object> jsonAsMap = new HashMap<>();
-        jsonAsMap.put( "grant_type", "authorization_code" );
-        jsonAsMap.put("user_id", userId);
-        jsonAsMap.put("password", password );
-        Response result = given( ).spec( getAuthRequestSpecBuilder().build() )
-            .contentType( JSON )
-            .body( jsonAsMap )
-            .when( ).post( "/authenticate").then( ).statusCode( 200 )
-            .extract( ).response( );
-        return result.body( ).jsonPath( ).getString( "access_token" );
-    }
-    protected String getAdminToken()  {
-        if (this.adminToken == null) {
-            initAdminToken();
-        }
-        return this.adminToken;
-    }
-
-
-    protected String getAdminRefreshToken()  {
-        if (this.adminRefreshToken == null) {
-            initAdminToken();
-        }
-        return this.adminRefreshToken;
-    }
-
-    public boolean isRemoteService() {
-        return this.remoteService;
-    }
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeMavenManagedRepositoryServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeMavenManagedRepositoryServiceTest.java
deleted file mode 100644 (file)
index f7d137f..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-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.path.json.JsonPath;
-import io.restassured.response.Response;
-import io.restassured.response.ResponseBody;
-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.MavenManagedRepository;
-import org.apache.archiva.rest.api.services.v2.RestConfiguration;
-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.Order;
-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 <martin_s@apache.org>
- */
-@TestInstance( TestInstance.Lifecycle.PER_CLASS )
-@Tag( "rest-native" )
-@TestMethodOrder( MethodOrderer.OrderAnnotation.class )
-@DisplayName( "Native REST tests for V2 ManagedRepositoryService" )
-public class NativeMavenManagedRepositoryServiceTest extends AbstractNativeRestServices
-{
-    @Override
-    protected String getServicePath( )
-    {
-        return "/repositories/maven/managed";
-    }
-
-    @BeforeAll
-    void setup( ) throws Exception
-    {
-        super.setupNative( );
-    }
-
-    @AfterAll
-    void destroy( ) throws Exception
-    {
-        super.shutdownNative( );
-    }
-
-    @Test
-    @Order( 1 )
-    void testGetRepositories( )
-    {
-        String token = getAdminToken( );
-        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .get( "" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        JsonPath json = response.getBody( ).jsonPath( );
-        assertEquals( 2, json.getInt( "pagination.total_count" ) );
-        assertEquals( 0, json.getInt( "pagination.offset" ) );
-        assertEquals( Integer.valueOf( RestConfiguration.DEFAULT_PAGE_LIMIT ), json.getInt( "pagination.limit" ) );
-        List<MavenManagedRepository> repositories = json.getList( "data", MavenManagedRepository.class );
-        assertEquals( "internal", repositories.get( 0 ).getId( ) );
-        assertEquals( "snapshots", repositories.get( 1 ).getId( ) );
-    }
-
-
-
-}
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
deleted file mode 100644 (file)
index 033a4a0..0000000
+++ /dev/null
@@ -1,471 +0,0 @@
-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.RepositoryGroup;
-import org.apache.archiva.rest.api.services.v2.ArchivaRestError;
-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.ArrayList;
-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.easymock.EasyMock.contains;
-import static org.hamcrest.Matchers.endsWith;
-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 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 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" );
-            jsonAsMap.put( "name", "group_001" );
-            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 = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .get( "" )
-                .then( ).statusCode( 200 ).extract( ).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" );
-            jsonAsMap.put( "name", "group_001" );
-            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonAsMap )
-                .post( "" )
-                .prettyPeek()
-                .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" );
-        }
-    }
-
-
-    @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 );
-                jsonAsMap.put( "name", 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 );
-            }
-        }
-    }
-
-    @Test
-    void testRemoveRepositoryGroup( )
-    {
-        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 );
-                jsonAsMap.put( "name", 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( )
-                .delete( "group_001" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( 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( 9, resultList.getPagination( ).getTotalCount( ) );
-
-
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .delete( "group_005" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( response );
-
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .get( "" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( response );
-            resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
-            assertEquals( 8, resultList.getPagination( ).getTotalCount( ) );
-
-        } finally
-        {
-            for (String groupName : groups)
-            {
-                if (!("group_001".equals(groupName) || "group_005".equals(groupName) ) )
-                {
-                    given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                        .when( )
-                        .delete( groupName );
-                }
-            }
-        }
-    }
-
-
-    @Test
-    void testAddRepositoryToGroup( )
-    {
-        String token = getAdminToken( );
-        try
-        {
-            Map<String, Object> jsonAsMap = new HashMap<>( );
-            jsonAsMap.put( "id", "group_001" );
-            jsonAsMap.put( "name", "group_001" );
-            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .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 );
-            PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
-            assertEquals( 1, resultList.getPagination( ).getTotalCount( ) );
-
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonAsMap )
-                .put( "group_001/repositories/internal" )
-                .prettyPeek()
-                .then( ).statusCode( 200 ).extract( ).response( );
-
-            assertNotNull( response );
-            result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class );
-            assertNotNull( result );
-            assertEquals( 1, result.getRepositories( ).size( ) );
-            assertTrue( result.getRepositories( ).contains( "internal" ) );
-
-        } finally
-        {
-            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .delete( "group_001" );
-        }
-    }
-
-    @Test
-    void testAddRepositoryToGroupIdempotency( )
-    {
-        String token = getAdminToken( );
-        try
-        {
-            Map<String, Object> jsonAsMap = new HashMap<>( );
-            jsonAsMap.put( "id", "group_001" );
-            jsonAsMap.put( "name", "group_001" );
-            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .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 );
-            PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
-            assertEquals( 1, resultList.getPagination( ).getTotalCount( ) );
-
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonAsMap )
-                .put( "group_001/repositories/internal" )
-                .prettyPeek()
-                .then( ).statusCode( 200 ).extract( ).response( );
-
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonAsMap )
-                .put( "group_001/repositories/internal" )
-                .prettyPeek()
-                .then( ).statusCode( 200 ).extract( ).response( );
-
-            assertNotNull( response );
-            result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class );
-            assertNotNull( result );
-            assertEquals( 1, result.getRepositories( ).size( ) );
-            assertTrue( result.getRepositories( ).contains( "internal" ) );
-
-        } finally
-        {
-            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .delete( "group_001" )
-                .then( ).statusCode( 200 );
-        }
-    }
-
-
-    @Test
-    void testRemoveRepositoryFromGroup( )
-    {
-        String token = getAdminToken( );
-        try
-        {
-            Map<String, Object> jsonAsMap = new HashMap<>( );
-            jsonAsMap.put( "id", "group_001" );
-            jsonAsMap.put( "name", "group_001" );
-            jsonAsMap.put( "repositories", Arrays.asList( "internal" ) );
-            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .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 );
-            PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
-            assertEquals( 1, resultList.getPagination( ).getTotalCount( ) );
-
-            assertNotNull( result.getRepositories( ) );
-            assertEquals( 1, result.getRepositories( ).size( ) );
-            assertTrue( result.getRepositories( ).contains( "internal" ) );
-
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonAsMap )
-                .delete( "group_001/repositories/internal" )
-                .prettyPeek()
-                .then( ).statusCode( 200 ).extract( ).response( );
-
-            assertNotNull( response );
-            result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class );
-            assertNotNull( result );
-            assertEquals( 0, result.getRepositories( ).size( ) );
-
-        } finally
-        {
-            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .delete( "group_001" )
-                .then( ).statusCode( 200 );
-        }
-    }
-
-    @Test
-    void testRemoveRepositoryFromGroup404( )
-    {
-        String token = getAdminToken( );
-        try
-        {
-            Map<String, Object> jsonAsMap = new HashMap<>( );
-            jsonAsMap.put( "id", "group_001" );
-            jsonAsMap.put( "name", "group_001" );
-            jsonAsMap.put( "repositories", Arrays.asList( "internal" ) );
-            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .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 );
-            PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
-            assertEquals( 1, resultList.getPagination( ).getTotalCount( ) );
-
-            assertNotNull( result.getRepositories( ) );
-            assertEquals( 1, result.getRepositories( ).size( ) );
-            assertTrue( result.getRepositories( ).contains( "internal" ) );
-
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonAsMap )
-                .delete( "group_001/repositories/internalxx" )
-                .prettyPeek()
-                .then( ).statusCode( 404 ).extract( ).response( );
-
-            assertNotNull( response );
-            ArchivaRestError error = response.getBody( ).jsonPath( ).getObject( "", ArchivaRestError.class );
-            assertNotNull( error );
-        } finally
-        {
-            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .delete( "group_001" );
-        }
-    }
-
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryServiceTest.java
deleted file mode 100644 (file)
index 1976fa1..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-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( "" )
-                .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( "" )
-            .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" )
-            .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" )
-            .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" )
-            .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" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        assertNotNull( response );
-
-    }
-
-    @Test
-    void scheduleIndexDownload() {
-        String token = getAdminToken( );
-        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .post( "remote/central/index/download/start" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        assertNotNull( response );
-    }
-
-    @Test
-    void getIndexDownloadList() {
-        String token = getAdminToken( );
-        given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .queryParam( "immediate", "true" )
-            .post( "remote/central/index/download/start" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .get( "remote/index/downloads" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        assertNotNull( response );
-        List<String> downloads = response.getBody( ).jsonPath( ).getList( "", String.class );
-        assertEquals( 1, downloads.size() );
-        assertEquals( "central", downloads.get( 0 ) );
-    }
-
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeSecurityConfigurationServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeSecurityConfigurationServiceTest.java
deleted file mode 100644 (file)
index 13b0a3e..0000000
+++ /dev/null
@@ -1,351 +0,0 @@
-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 org.junit.jupiter.api.extension.ExtendWith;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-
-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 <martin_s@apache.org>
- */
-@TestInstance( TestInstance.Lifecycle.PER_CLASS )
-@Tag( "rest-native" )
-@TestMethodOrder( MethodOrderer.Random.class )
-@DisplayName( "Native REST tests for V2 SecurityConfigurationService" )
-public class NativeSecurityConfigurationServiceTest extends AbstractNativeRestServices
-{
-    @Override
-    protected String getServicePath( )
-    {
-        return "/security";
-    }
-
-    @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( "config" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-        assertNotNull( response );
-        assertEquals( "jpa", response.getBody( ).jsonPath( ).getString( "active_user_managers[0]" ) );
-        assertEquals( "jpa", response.getBody( ).jsonPath( ).getString( "active_rbac_managers[0]" ) );
-        assertEquals( "memory", response.getBody( ).jsonPath( ).getString( "properties.\"authentication.jwt.keystoreType\"" ) );
-        assertEquals("10",response.getBody( ).jsonPath( ).getString( "properties.\"security.policy.allowed.login.attempt\""));
-        assertTrue( response.getBody( ).jsonPath( ).getBoolean( "user_cache_enabled" ) );
-        assertFalse( response.getBody( ).jsonPath( ).getBoolean( "ldap_active" ) );
-    }
-
-    @Test
-    void testGetConfigurationProperties() {
-        String token = getAdminToken( );
-        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .get( "config/properties" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        assertNotNull( response );
-        PagedResult<PropertyEntry> result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
-        List<PropertyEntry> propList = response.getBody( ).jsonPath( ).getList( "data", PropertyEntry.class );
-        assertEquals( 10, result.getPagination( ).getLimit( ) );
-        assertEquals( 0, result.getPagination( ).getOffset( ) );
-        assertEquals( 47, result.getPagination( ).getTotalCount( ) );
-        assertEquals( "authentication.jwt.keystoreType", propList.get( 0 ).getKey() );
-
-        response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .queryParam( "offset", "3" )
-            .queryParam( "limit", "5" )
-            .get( "config/properties" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-
-        assertNotNull( response );
-        result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
-        assertEquals( 5, result.getPagination( ).getLimit( ) );
-        assertEquals( 47, result.getPagination( ).getTotalCount( ) );
-        propList = response.getBody( ).jsonPath( ).getList( "data", PropertyEntry.class );
-        assertEquals( "authentication.jwt.refreshLifetimeMs", propList.get( 0 ).getKey() );
-    }
-
-    @Test
-    void testGetLdapConfiguration() {
-        String token = getAdminToken( );
-        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .get( "config/ldap" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        assertNotNull( response );
-        assertEquals( "", response.getBody( ).jsonPath( ).get( "host_name" ) );
-        assertEquals( 0, response.getBody( ).jsonPath( ).getMap( "properties" ).size( ) );
-    }
-
-
-    @Test
-    void testUpdateLdapConfiguration() {
-        String token = getAdminToken( );
-        try
-        {
-            Map<String, Object> jsonMap = new HashMap<>( );
-            jsonMap.put( "host_name", "localhost" );
-            jsonMap.put( "port", 389 );
-            jsonMap.put( "ssl_enabled", false );
-            jsonMap.put( "writable", true );
-            jsonMap.put( "base_dn", "dc=apache,dc=org" );
-            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonMap )
-                .put( "config/ldap" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( response );
-
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .get( "config/ldap" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( response );
-            LdapConfiguration config = response.getBody( ).jsonPath( ).getObject( "", LdapConfiguration.class );
-            assertEquals( "localhost", config.getHostName( ) );
-            assertEquals( 389, config.getPort( ) );
-            assertFalse( config.isSslEnabled( ) );
-            assertTrue( config.isWritable( ) );
-            assertEquals( "dc=apache,dc=org", config.getBaseDn( ) );
-        } finally
-        {
-            Map<String, Object> jsonMap = new HashMap<>( );
-            jsonMap.put( "host_name", "" );
-            jsonMap.put( "port", -1 );
-            jsonMap.put( "ssl_enabled", false );
-            jsonMap.put( "base_dn", "" );
-            jsonMap.put( "writable", false );
-            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonMap )
-                .put( "config/ldap" )
-                .then( ).statusCode( 200 );
-
-        }
-    }
-
-
-    @Test
-    void testGetCacheConfiguration() {
-        String token = getAdminToken( );
-        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .get( "config/cache" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        assertNotNull( response );
-    }
-
-    @Test
-    void testUpdateCacheConfiguration() {
-        String token = getAdminToken( );
-
-        try
-        {
-            Map<String, Object> jsonMap = new HashMap<>( );
-            jsonMap.put( "time_to_idle_seconds", 1600 );
-            jsonMap.put( "time_to_live_seconds", 12000 );
-            jsonMap.put( "max_entries_in_memory", 500 );
-            jsonMap.put( "max_entries_on_disk", 400 );
-
-            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonMap )
-                .put( "config/cache" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( response );
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .get( "config/cache" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( response );
-            CacheConfiguration config = response.getBody( ).jsonPath( ).getObject( "", CacheConfiguration.class );
-            assertEquals( 1600, config.getTimeToIdleSeconds( ) );
-            assertEquals( 12000, config.getTimeToLiveSeconds( ) );
-            assertEquals( 500, config.getMaxEntriesInMemory( ) );
-            assertEquals( 400, config.getMaxEntriesOnDisk( ) );
-        } finally
-        {
-            Map<String, Object> jsonMap = new HashMap<>( );
-            jsonMap.put( "time_to_idle_seconds", 1800 );
-            jsonMap.put( "time_to_live_seconds", 14400 );
-            jsonMap.put( "max_entries_in_memory", 1000 );
-            jsonMap.put( "max_entries_on_disk", 0 );
-
-            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonMap )
-                .put( "config/cache" )
-                .then( ).statusCode( 200 );
-
-        }
-    }
-
-
-    @Test
-    void testGetUserManagers() {
-        String token = getAdminToken( );
-        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .get( "user_managers" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        assertNotNull( response );
-        List<BeanInformation> usrList = response.getBody( ).jsonPath( ).getList( "", BeanInformation.class );
-        assertEquals( 2, usrList.size( ) );
-        assertTrue( usrList.stream( ).anyMatch( bi -> "LDAP User Manager".equals( bi.getDisplayName( ) ) ) );
-        assertTrue( usrList.stream( ).anyMatch( bi -> "Database User Manager".equals( bi.getDisplayName( ) ) ) );
-    }
-
-    @Test
-    void testGetRbacManagers() {
-        String token = getAdminToken( );
-        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .get( "rbac_managers" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        assertNotNull( response );
-        List<BeanInformation> rbacList = response.getBody( ).jsonPath( ).getList( "", BeanInformation.class );
-        assertEquals( 2, rbacList.size( ) );
-        assertTrue( rbacList.stream( ).anyMatch( bi -> "Database RBAC Manager".equals( bi.getDisplayName( ) ) ) );
-        assertTrue( rbacList.stream( ).anyMatch( bi -> "LDAP RBAC Manager".equals( bi.getDisplayName( ) ) ) );
-    }
-
-    @Test
-    void testUpdateConfiguration() {
-        String token = getAdminToken( );
-        try
-        {
-            Map<String, Object> jsonAsMap = new HashMap<>( );
-            jsonAsMap.put( "active_user_managers", Arrays.asList( "jpa", "ldap" ) );
-            jsonAsMap.put( "active_rbac_managers", Arrays.asList( "jpa" ) );
-            jsonAsMap.put( "user_cache_enabled", false );
-            jsonAsMap.put( "ldap_active", false );
-            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonAsMap )
-                .put( "config" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( response );
-
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .get( "config" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( response );
-            assertEquals( 2, response.getBody( ).jsonPath( ).getList( "active_user_managers" ).size( ) );
-        } finally
-        {
-            Map<String, Object> jsonAsMap = new HashMap<>( );
-            jsonAsMap.put( "active_user_managers", Arrays.asList( "jpa" ) );
-            jsonAsMap.put( "active_rbac_managers", Arrays.asList( "jpa" ) );
-            jsonAsMap.put( "user_cache_enabled", true );
-            jsonAsMap.put( "ldap_active", false );
-            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonAsMap )
-                .put( "config" )
-                .then( ).statusCode( 200 );
-
-        }
-
-    }
-
-    @Test
-    void testGetConfigProperty() {
-        String token = getAdminToken( );
-        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-            .when( )
-            .get( "config/properties/rest.csrffilter.absentorigin.deny" )
-            .then( ).statusCode( 200 ).extract( ).response( );
-        assertNotNull( response );
-        assertEquals( "true", response.getBody( ).jsonPath( ).getString( "value" ) );
-    }
-
-    @Test
-    void testUpdateConfigProperty() {
-        String token = getAdminToken( );
-
-        try
-        {
-            Map<String, String> jsonMap = new HashMap<>( );
-            jsonMap.put( "value", "false" );
-            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonMap )
-                .put( "config/properties/rest.csrffilter.absentorigin.deny" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( response );
-
-
-            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .get( "config/properties/rest.csrffilter.absentorigin.deny" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-            assertNotNull( response );
-            assertEquals( "false", response.getBody( ).jsonPath( ).getString( "value" ) );
-        } finally
-        {
-            Map<String, String> jsonMap = new HashMap<>( );
-            jsonMap.put( "value", "true" );
-            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
-                .when( )
-                .body( jsonMap )
-                .put( "config/properties/rest.csrffilter.absentorigin.deny" )
-                .then( ).statusCode( 200 ).extract( ).response( );
-        }
-    }
-
-
-}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/AbstractNativeRestServices.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/AbstractNativeRestServices.java
new file mode 100644 (file)
index 0000000..4949e55
--- /dev/null
@@ -0,0 +1,512 @@
+package org.apache.archiva.rest.v2.svc;
+
+/*
+ * 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 com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyNamingStrategy;
+import io.restassured.RestAssured;
+import io.restassured.builder.RequestSpecBuilder;
+import io.restassured.config.ObjectMapperConfig;
+import io.restassured.config.RestAssuredConfig;
+import io.restassured.path.json.mapper.factory.Jackson2ObjectMapperFactory;
+import io.restassured.response.Response;
+import io.restassured.specification.RequestSpecification;
+import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants;
+import org.apache.archiva.redback.rest.services.BaseSetup;
+import org.apache.archiva.redback.role.RoleManager;
+import org.apache.archiva.redback.role.RoleManagerException;
+import org.apache.archiva.redback.users.User;
+import org.apache.archiva.redback.users.UserManager;
+import org.apache.archiva.redback.users.UserManagerException;
+import org.apache.archiva.redback.users.UserNotFoundException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.SystemUtils;
+import org.apache.cxf.transport.servlet.CXFServlet;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.session.SessionHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.jupiter.api.Tag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.context.ContextLoaderListener;
+
+import java.lang.reflect.Type;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalTime;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static io.restassured.RestAssured.*;
+import static io.restassured.http.ContentType.JSON;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * Native REST tests do not use the JAX-RS client and can be used with a remote
+ * REST API service. The tests
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Tag( "rest-native" )
+@Tag( "rest-v2" )
+public abstract class AbstractNativeRestServices
+{
+    private AtomicReference<Path> projectDir = new AtomicReference<>();
+    private AtomicReference<Path> appServerBase = new AtomicReference<>( );
+    private AtomicReference<Path> basePath = new AtomicReference<>( );
+
+    public static final int STOPPED = 0;
+    public static final int STOPPING = 1;
+    public static final int STARTING = 2;
+    public static final int STARTED = 3;
+    public static final int ERROR = 4;
+    private final boolean startServer;
+    private final String serverPort;
+    private final String baseUri;
+
+    private RequestSpecification requestSpec;
+    protected Logger log = LoggerFactory.getLogger( getClass( ) );
+
+    private static AtomicReference<Server> server = new AtomicReference<>( );
+    private static AtomicReference<ServerConnector> serverConnector = new AtomicReference<>( );
+    private static AtomicInteger serverStarted = new AtomicInteger( STOPPED );
+    private UserManager userManager;
+    private RoleManager roleManager;
+
+    private final boolean remoteService;
+
+    private String adminToken;
+    private String adminRefreshToken;
+
+
+    public AbstractNativeRestServices( )
+    {
+        this.startServer = BaseSetup.startServer( );
+        this.serverPort = BaseSetup.getServerPort( );
+        this.baseUri = BaseSetup.getBaseUri( );
+
+        if ( startServer )
+        {
+            this.remoteService = false;
+        } else {
+            this.remoteService = true;
+        }
+    }
+
+    protected abstract String getServicePath( );
+
+    protected String getSpringConfigLocation( )
+    {
+        return "classpath*:META-INF/spring-context.xml,classpath:META-INF/spring-context-native-test.xml";
+    }
+
+    protected RequestSpecification getRequestSpec( )
+    {
+        return this.requestSpec;
+    }
+
+    protected String getContextRoot( )
+    {
+        return "/api";
+    }
+
+
+    protected String getServiceBasePath( )
+    {
+        return "/v2/archiva";
+    }
+
+    protected String getRedbackServiceBasePath( )
+    {
+        return "/v2/redback";
+    }
+
+
+    protected String getBasePath( )
+    {
+        return new StringBuilder( )
+            .append( getContextRoot( ) )
+            .append( getServiceBasePath( ) )
+            .append( getServicePath( ) ).toString( );
+    }
+
+    /**
+     * Returns the server that was started, or null if not initialized before.
+     *
+     * @return
+     */
+    public Server getServer( )
+    {
+        return this.server.get( );
+    }
+
+    public int getServerPort( )
+    {
+        ServerConnector connector = serverConnector.get( );
+        if ( connector != null )
+        {
+            return connector.getLocalPort( );
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    /**
+     * Returns true, if the server does exist and is running.
+     *
+     * @return true, if server does exist and is running.
+     */
+    public boolean isServerRunning( )
+    {
+        return serverStarted.get( ) == STARTED && this.server.get( ) != null && this.server.get( ).isRunning( );
+    }
+
+    private UserManager getUserManager( )
+    {
+        if ( this.userManager == null )
+        {
+            UserManager userManager = ContextLoaderListener.getCurrentWebApplicationContext( )
+                .getBean( "userManager#default", UserManager.class );
+            assertNotNull( userManager );
+            this.userManager = userManager;
+        }
+        return this.userManager;
+    }
+
+    private RoleManager getRoleManager( )
+    {
+        if ( this.roleManager == null )
+        {
+            RoleManager roleManager = ContextLoaderListener.getCurrentWebApplicationContext( )
+                .getBean( "roleManager", RoleManager.class );
+            assertNotNull( roleManager );
+            this.roleManager = roleManager;
+        }
+        return this.roleManager;
+    }
+
+    protected String getAdminPwd( )
+    {
+        return BaseSetup.getAdminPwd( );
+    }
+
+    protected String getAdminUser( )
+    {
+        return RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME;
+    }
+
+    private void setupAdminUser( ) throws UserManagerException, RoleManagerException
+    {
+
+        UserManager um = getUserManager( );
+
+        User adminUser = null;
+        try
+        {
+            adminUser = um.findUser( getAdminUser( ) );
+        }
+        catch ( UserNotFoundException e )
+        {
+            // ignore
+        }
+        adminUser = um.createUser( getAdminUser( ), "Administrator", "admin@local.home" );
+        adminUser.setUsername( getAdminUser( ) );
+        adminUser.setPassword( getAdminPwd( ) );
+        adminUser.setFullName( "the admin user" );
+        adminUser.setEmail( "toto@toto.fr" );
+        adminUser.setPermanent( true );
+        adminUser.setValidated( true );
+        adminUser.setLocked( false );
+        adminUser.setPasswordChangeRequired( false );
+        if ( adminUser == null )
+        {
+            um.addUser( adminUser );
+        }
+        else
+        {
+            um.updateUser( adminUser, false );
+        }
+        getRoleManager( ).assignRole( "system-administrator", adminUser.getUsername( ) );
+    }
+
+    protected Path getProjectDirectory() {
+        if ( projectDir.get()==null) {
+            String propVal = System.getProperty("mvn.project.base.dir");
+            Path newVal;
+            if (StringUtils.isEmpty(propVal)) {
+                newVal = Paths.get("").toAbsolutePath();
+            } else {
+                newVal = Paths.get(propVal).toAbsolutePath();
+            }
+            projectDir.compareAndSet(null, newVal);
+        }
+        return projectDir.get();
+    }
+
+    public Path getBasedir()
+    {
+        if (basePath.get()==null) {
+            String baseDir = System.getProperty( "basedir" );
+            final Path baseDirPath;
+            if (StringUtils.isNotEmpty( baseDir ))  {
+                baseDirPath = Paths.get( baseDir );
+            } else {
+                baseDirPath = getProjectDirectory( );
+            }
+            basePath.compareAndSet( null, baseDirPath );
+        }
+        return basePath.get( );
+    }
+
+    Path getAppserverBase() {
+        if (appServerBase.get()==null) {
+            String basePath = System.getProperty( "appserver.base" );
+            final Path appserverPath;
+            if (StringUtils.isNotEmpty( basePath )) {
+                appserverPath = Paths.get( basePath ).toAbsolutePath( );
+            } else {
+                appserverPath = getBasedir( ).resolve( "target" ).resolve( "appserver-base-" + LocalTime.now( ).toSecondOfDay( ) );
+            }
+            appServerBase.compareAndSet( null, appserverPath );
+        }
+        return appServerBase.get();
+    }
+
+    private void removeAppsubFolder( Path appServerBase, String folder )
+        throws Exception
+    {
+        Path directory = appServerBase.resolve( folder );
+        if ( Files.exists(directory) )
+        {
+            org.apache.archiva.common.utils.FileUtils.deleteDirectory( directory );
+        }
+    }
+
+    public void startServer( )
+        throws Exception
+    {
+        if ( serverStarted.compareAndSet( STOPPED, STARTING ) )
+        {
+            try
+            {
+                log.info( "Starting server" );
+                Path appServerBase = getAppserverBase( );
+
+                removeAppsubFolder(appServerBase, "jcr");
+                removeAppsubFolder(appServerBase, "conf");
+                removeAppsubFolder(appServerBase, "data");
+
+
+                Server myServer = new Server( );
+                this.server.set( myServer );
+                this.serverConnector.set( new ServerConnector( myServer, new HttpConnectionFactory( ) ) );
+                myServer.addConnector( serverConnector.get( ) );
+
+                ServletHolder servletHolder = new ServletHolder( new CXFServlet( ) );
+                ServletContextHandler context = new ServletContextHandler( ServletContextHandler.SESSIONS );
+                context.setResourceBase( SystemUtils.JAVA_IO_TMPDIR );
+                context.setSessionHandler( new SessionHandler( ) );
+                context.addServlet( servletHolder, getContextRoot( ) + "/*" );
+                context.setInitParameter( "contextConfigLocation", getSpringConfigLocation( ) );
+                context.addEventListener( new ContextLoaderListener( ) );
+
+                getServer( ).setHandler( context );
+                getServer( ).start( );
+
+                if ( log.isDebugEnabled( ) )
+                {
+                    log.debug( "Jetty dump: {}", getServer( ).dump( ) );
+                }
+
+                setupAdminUser( );
+                log.info( "Started server on port {}", getServerPort( ) );
+                serverStarted.set( STARTED );
+            }
+            finally
+            {
+                // In case, if the last statement was not reached
+                serverStarted.compareAndSet( STARTING, ERROR );
+            }
+        }
+
+    }
+
+    public void stopServer( )
+        throws Exception
+    {
+        if ( this.serverStarted.compareAndSet( STARTED, STOPPING ) )
+        {
+            try
+            {
+                final Server myServer = getServer( );
+                if ( myServer != null )
+                {
+                    log.info( "Stopping server" );
+                    myServer.stop( );
+                }
+                serverStarted.set( STOPPED );
+            }
+            finally
+            {
+                serverStarted.compareAndSet( STOPPING, ERROR );
+            }
+        }
+        else
+        {
+            log.error( "Server is not in STARTED state!" );
+        }
+    }
+
+
+    protected void setupNative( ) throws Exception
+    {
+        if ( this.startServer )
+        {
+            startServer( );
+        }
+
+        if ( StringUtils.isNotEmpty( serverPort ) )
+        {
+            RestAssured.port = Integer.parseInt( serverPort );
+        }
+        else
+        {
+            RestAssured.port = getServerPort( );
+        }
+        if ( StringUtils.isNotEmpty( baseUri ) )
+        {
+            RestAssured.baseURI = baseUri;
+        }
+        else
+        {
+            RestAssured.baseURI = "http://localhost";
+        }
+        String basePath = getBasePath( );
+        this.requestSpec = getRequestSpecBuilder( ).build( );
+        RestAssured.basePath = basePath;
+        RestAssured.config = RestAssuredConfig.config().objectMapperConfig(new ObjectMapperConfig().jackson2ObjectMapperFactory(
+            ( cls, charset ) -> {
+                ObjectMapper om = new ObjectMapper().findAndRegisterModules();
+                om.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+                om.setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE );
+                return om;
+            }
+        ));
+    }
+
+    protected RequestSpecBuilder getRequestSpecBuilder( ) {
+        return getRequestSpecBuilder( null );
+    }
+
+    protected RequestSpecBuilder getRequestSpecBuilder( String basePath )
+    {
+        String myBasePath = basePath == null ? getBasePath( ) : basePath;
+        return new RequestSpecBuilder( ).setBaseUri( baseURI )
+            .setPort( port )
+            .setBasePath( myBasePath )
+            .addHeader( "Origin", RestAssured.baseURI + ":" + RestAssured.port );
+    }
+
+    protected RequestSpecBuilder getAuthRequestSpecBuilder( )
+    {
+        return new RequestSpecBuilder( ).setBaseUri( baseURI )
+            .setPort( port )
+            .setBasePath( new StringBuilder( )
+                .append( getContextRoot( ) )
+                .append( getRedbackServiceBasePath() ).append("/auth").toString() )
+            .addHeader( "Origin", RestAssured.baseURI + ":" + RestAssured.port );
+    }
+
+    protected RequestSpecification getRequestSpec( String bearerToken )
+    {
+        return getRequestSpecBuilder( ).addHeader( "Authorization", "Bearer " + bearerToken ).build( );
+    }
+
+    protected RequestSpecification getRequestSpec( String bearerToken, String path)
+    {
+        return getRequestSpecBuilder( path  ).addHeader( "Authorization", "Bearer " + bearerToken ).build( );
+    }
+
+    protected void shutdownNative( ) throws Exception
+    {
+        if (startServer)
+        {
+            stopServer( );
+        }
+    }
+
+    protected org.apache.archiva.redback.rest.api.model.User addRemoteUser(String userid, String password, String fullName, String mail) {
+
+        return null;
+    }
+
+    protected void initAdminToken() {
+        Map<String, Object> jsonAsMap = new HashMap<>();
+        jsonAsMap.put( "grant_type", "authorization_code" );
+        jsonAsMap.put("user_id", getAdminUser());
+        jsonAsMap.put("password", getAdminPwd() );
+        Response result = given( ).spec( getAuthRequestSpecBuilder().build() )
+            .contentType( JSON )
+            .body( jsonAsMap )
+            .when( ).post( "/authenticate").then( ).statusCode( 200 )
+            .extract( ).response( );
+        this.adminToken = result.body( ).jsonPath( ).getString( "access_token" );
+        this.adminRefreshToken = result.body( ).jsonPath( ).getString( "refresh_token" );
+    }
+
+    protected String getUserToken(String userId, String password) {
+        Map<String, Object> jsonAsMap = new HashMap<>();
+        jsonAsMap.put( "grant_type", "authorization_code" );
+        jsonAsMap.put("user_id", userId);
+        jsonAsMap.put("password", password );
+        Response result = given( ).spec( getAuthRequestSpecBuilder().build() )
+            .contentType( JSON )
+            .body( jsonAsMap )
+            .when( ).post( "/authenticate").then( ).statusCode( 200 )
+            .extract( ).response( );
+        return result.body( ).jsonPath( ).getString( "access_token" );
+    }
+    protected String getAdminToken()  {
+        if (this.adminToken == null) {
+            initAdminToken();
+        }
+        return this.adminToken;
+    }
+
+
+    protected String getAdminRefreshToken()  {
+        if (this.adminRefreshToken == null) {
+            initAdminToken();
+        }
+        return this.adminRefreshToken;
+    }
+
+    public boolean isRemoteService() {
+        return this.remoteService;
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeMavenManagedRepositoryServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeMavenManagedRepositoryServiceTest.java
new file mode 100644 (file)
index 0000000..d078b45
--- /dev/null
@@ -0,0 +1,88 @@
+package org.apache.archiva.rest.v2.svc;
+
+/*
+ * 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.path.json.JsonPath;
+import io.restassured.response.Response;
+import org.apache.archiva.rest.api.v2.model.MavenManagedRepository;
+import org.apache.archiva.rest.api.v2.svc.RestConfiguration;
+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.Order;
+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.OrderAnnotation.class )
+@DisplayName( "Native REST tests for V2 ManagedRepositoryService" )
+public class NativeMavenManagedRepositoryServiceTest extends AbstractNativeRestServices
+{
+    @Override
+    protected String getServicePath( )
+    {
+        return "/repositories/maven/managed";
+    }
+
+    @BeforeAll
+    void setup( ) throws Exception
+    {
+        super.setupNative( );
+    }
+
+    @AfterAll
+    void destroy( ) throws Exception
+    {
+        super.shutdownNative( );
+    }
+
+    @Test
+    @Order( 1 )
+    void testGetRepositories( )
+    {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .get( "" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        JsonPath json = response.getBody( ).jsonPath( );
+        assertEquals( 2, json.getInt( "pagination.total_count" ) );
+        assertEquals( 0, json.getInt( "pagination.offset" ) );
+        assertEquals( Integer.valueOf( RestConfiguration.DEFAULT_PAGE_LIMIT ), json.getInt( "pagination.limit" ) );
+        List<MavenManagedRepository> repositories = json.getList( "data", MavenManagedRepository.class );
+        assertEquals( "internal", repositories.get( 0 ).getId( ) );
+        assertEquals( "snapshots", repositories.get( 1 ).getId( ) );
+    }
+
+
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryGroupServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryGroupServiceTest.java
new file mode 100644 (file)
index 0000000..9abb5e4
--- /dev/null
@@ -0,0 +1,470 @@
+package org.apache.archiva.rest.v2.svc;
+
+/*
+ * 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.v2.model.RepositoryGroup;
+import org.apache.archiva.rest.api.v2.svc.ArchivaRestError;
+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.ArrayList;
+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.hamcrest.Matchers.endsWith;
+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 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 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" );
+            jsonAsMap.put( "name", "group_001" );
+            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 = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .get( "" )
+                .then( ).statusCode( 200 ).extract( ).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" );
+            jsonAsMap.put( "name", "group_001" );
+            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonAsMap )
+                .post( "" )
+                .prettyPeek()
+                .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" );
+        }
+    }
+
+
+    @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 );
+                jsonAsMap.put( "name", 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 );
+            }
+        }
+    }
+
+    @Test
+    void testRemoveRepositoryGroup( )
+    {
+        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 );
+                jsonAsMap.put( "name", 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( )
+                .delete( "group_001" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( 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( 9, resultList.getPagination( ).getTotalCount( ) );
+
+
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .delete( "group_005" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( response );
+
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .get( "" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( response );
+            resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+            assertEquals( 8, resultList.getPagination( ).getTotalCount( ) );
+
+        } finally
+        {
+            for (String groupName : groups)
+            {
+                if (!("group_001".equals(groupName) || "group_005".equals(groupName) ) )
+                {
+                    given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                        .when( )
+                        .delete( groupName );
+                }
+            }
+        }
+    }
+
+
+    @Test
+    void testAddRepositoryToGroup( )
+    {
+        String token = getAdminToken( );
+        try
+        {
+            Map<String, Object> jsonAsMap = new HashMap<>( );
+            jsonAsMap.put( "id", "group_001" );
+            jsonAsMap.put( "name", "group_001" );
+            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .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 );
+            PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+            assertEquals( 1, resultList.getPagination( ).getTotalCount( ) );
+
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonAsMap )
+                .put( "group_001/repositories/internal" )
+                .prettyPeek()
+                .then( ).statusCode( 200 ).extract( ).response( );
+
+            assertNotNull( response );
+            result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class );
+            assertNotNull( result );
+            assertEquals( 1, result.getRepositories( ).size( ) );
+            assertTrue( result.getRepositories( ).contains( "internal" ) );
+
+        } finally
+        {
+            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .delete( "group_001" );
+        }
+    }
+
+    @Test
+    void testAddRepositoryToGroupIdempotency( )
+    {
+        String token = getAdminToken( );
+        try
+        {
+            Map<String, Object> jsonAsMap = new HashMap<>( );
+            jsonAsMap.put( "id", "group_001" );
+            jsonAsMap.put( "name", "group_001" );
+            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .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 );
+            PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+            assertEquals( 1, resultList.getPagination( ).getTotalCount( ) );
+
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonAsMap )
+                .put( "group_001/repositories/internal" )
+                .prettyPeek()
+                .then( ).statusCode( 200 ).extract( ).response( );
+
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonAsMap )
+                .put( "group_001/repositories/internal" )
+                .prettyPeek()
+                .then( ).statusCode( 200 ).extract( ).response( );
+
+            assertNotNull( response );
+            result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class );
+            assertNotNull( result );
+            assertEquals( 1, result.getRepositories( ).size( ) );
+            assertTrue( result.getRepositories( ).contains( "internal" ) );
+
+        } finally
+        {
+            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .delete( "group_001" )
+                .then( ).statusCode( 200 );
+        }
+    }
+
+
+    @Test
+    void testRemoveRepositoryFromGroup( )
+    {
+        String token = getAdminToken( );
+        try
+        {
+            Map<String, Object> jsonAsMap = new HashMap<>( );
+            jsonAsMap.put( "id", "group_001" );
+            jsonAsMap.put( "name", "group_001" );
+            jsonAsMap.put( "repositories", Arrays.asList( "internal" ) );
+            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .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 );
+            PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+            assertEquals( 1, resultList.getPagination( ).getTotalCount( ) );
+
+            assertNotNull( result.getRepositories( ) );
+            assertEquals( 1, result.getRepositories( ).size( ) );
+            assertTrue( result.getRepositories( ).contains( "internal" ) );
+
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonAsMap )
+                .delete( "group_001/repositories/internal" )
+                .prettyPeek()
+                .then( ).statusCode( 200 ).extract( ).response( );
+
+            assertNotNull( response );
+            result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class );
+            assertNotNull( result );
+            assertEquals( 0, result.getRepositories( ).size( ) );
+
+        } finally
+        {
+            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .delete( "group_001" )
+                .then( ).statusCode( 200 );
+        }
+    }
+
+    @Test
+    void testRemoveRepositoryFromGroup404( )
+    {
+        String token = getAdminToken( );
+        try
+        {
+            Map<String, Object> jsonAsMap = new HashMap<>( );
+            jsonAsMap.put( "id", "group_001" );
+            jsonAsMap.put( "name", "group_001" );
+            jsonAsMap.put( "repositories", Arrays.asList( "internal" ) );
+            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .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 );
+            PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+            assertEquals( 1, resultList.getPagination( ).getTotalCount( ) );
+
+            assertNotNull( result.getRepositories( ) );
+            assertEquals( 1, result.getRepositories( ).size( ) );
+            assertTrue( result.getRepositories( ).contains( "internal" ) );
+
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonAsMap )
+                .delete( "group_001/repositories/internalxx" )
+                .prettyPeek()
+                .then( ).statusCode( 404 ).extract( ).response( );
+
+            assertNotNull( response );
+            ArchivaRestError error = response.getBody( ).jsonPath( ).getObject( "", ArchivaRestError.class );
+            assertNotNull( error );
+        } finally
+        {
+            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .delete( "group_001" );
+        }
+    }
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryServiceTest.java
new file mode 100644 (file)
index 0000000..783047c
--- /dev/null
@@ -0,0 +1,185 @@
+package org.apache.archiva.rest.v2.svc;
+
+/*
+ * 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.v2.model.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( "" )
+                .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( "" )
+            .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" )
+            .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" )
+            .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" )
+            .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" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+
+    }
+
+    @Test
+    void scheduleIndexDownload() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .post( "remote/central/index/download/start" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+    }
+
+    @Test
+    void getIndexDownloadList() {
+        String token = getAdminToken( );
+        given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .queryParam( "immediate", "true" )
+            .post( "remote/central/index/download/start" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .get( "remote/index/downloads" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+        List<String> downloads = response.getBody( ).jsonPath( ).getList( "", String.class );
+        assertEquals( 1, downloads.size() );
+        assertEquals( "central", downloads.get( 0 ) );
+    }
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeSecurityConfigurationServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeSecurityConfigurationServiceTest.java
new file mode 100644 (file)
index 0000000..0eadb67
--- /dev/null
@@ -0,0 +1,348 @@
+package org.apache.archiva.rest.v2.svc;
+
+/*
+ * 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.v2.model.BeanInformation;
+import org.apache.archiva.rest.api.v2.model.CacheConfiguration;
+import org.apache.archiva.rest.api.v2.model.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 <martin_s@apache.org>
+ */
+@TestInstance( TestInstance.Lifecycle.PER_CLASS )
+@Tag( "rest-native" )
+@TestMethodOrder( MethodOrderer.Random.class )
+@DisplayName( "Native REST tests for V2 SecurityConfigurationService" )
+public class NativeSecurityConfigurationServiceTest extends AbstractNativeRestServices
+{
+    @Override
+    protected String getServicePath( )
+    {
+        return "/security";
+    }
+
+    @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( "config" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+        assertEquals( "jpa", response.getBody( ).jsonPath( ).getString( "active_user_managers[0]" ) );
+        assertEquals( "jpa", response.getBody( ).jsonPath( ).getString( "active_rbac_managers[0]" ) );
+        assertEquals( "memory", response.getBody( ).jsonPath( ).getString( "properties.\"authentication.jwt.keystoreType\"" ) );
+        assertEquals("10",response.getBody( ).jsonPath( ).getString( "properties.\"security.policy.allowed.login.attempt\""));
+        assertTrue( response.getBody( ).jsonPath( ).getBoolean( "user_cache_enabled" ) );
+        assertFalse( response.getBody( ).jsonPath( ).getBoolean( "ldap_active" ) );
+    }
+
+    @Test
+    void testGetConfigurationProperties() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .get( "config/properties" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+        PagedResult<PropertyEntry> result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+        List<PropertyEntry> propList = response.getBody( ).jsonPath( ).getList( "data", PropertyEntry.class );
+        assertEquals( 10, result.getPagination( ).getLimit( ) );
+        assertEquals( 0, result.getPagination( ).getOffset( ) );
+        assertEquals( 47, result.getPagination( ).getTotalCount( ) );
+        assertEquals( "authentication.jwt.keystoreType", propList.get( 0 ).getKey() );
+
+        response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .queryParam( "offset", "3" )
+            .queryParam( "limit", "5" )
+            .get( "config/properties" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+
+        assertNotNull( response );
+        result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+        assertEquals( 5, result.getPagination( ).getLimit( ) );
+        assertEquals( 47, result.getPagination( ).getTotalCount( ) );
+        propList = response.getBody( ).jsonPath( ).getList( "data", PropertyEntry.class );
+        assertEquals( "authentication.jwt.refreshLifetimeMs", propList.get( 0 ).getKey() );
+    }
+
+    @Test
+    void testGetLdapConfiguration() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .get( "config/ldap" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+        assertEquals( "", response.getBody( ).jsonPath( ).get( "host_name" ) );
+        assertEquals( 0, response.getBody( ).jsonPath( ).getMap( "properties" ).size( ) );
+    }
+
+
+    @Test
+    void testUpdateLdapConfiguration() {
+        String token = getAdminToken( );
+        try
+        {
+            Map<String, Object> jsonMap = new HashMap<>( );
+            jsonMap.put( "host_name", "localhost" );
+            jsonMap.put( "port", 389 );
+            jsonMap.put( "ssl_enabled", false );
+            jsonMap.put( "writable", true );
+            jsonMap.put( "base_dn", "dc=apache,dc=org" );
+            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonMap )
+                .put( "config/ldap" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( response );
+
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .get( "config/ldap" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( response );
+            LdapConfiguration config = response.getBody( ).jsonPath( ).getObject( "", LdapConfiguration.class );
+            assertEquals( "localhost", config.getHostName( ) );
+            assertEquals( 389, config.getPort( ) );
+            assertFalse( config.isSslEnabled( ) );
+            assertTrue( config.isWritable( ) );
+            assertEquals( "dc=apache,dc=org", config.getBaseDn( ) );
+        } finally
+        {
+            Map<String, Object> jsonMap = new HashMap<>( );
+            jsonMap.put( "host_name", "" );
+            jsonMap.put( "port", -1 );
+            jsonMap.put( "ssl_enabled", false );
+            jsonMap.put( "base_dn", "" );
+            jsonMap.put( "writable", false );
+            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonMap )
+                .put( "config/ldap" )
+                .then( ).statusCode( 200 );
+
+        }
+    }
+
+
+    @Test
+    void testGetCacheConfiguration() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .get( "config/cache" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+    }
+
+    @Test
+    void testUpdateCacheConfiguration() {
+        String token = getAdminToken( );
+
+        try
+        {
+            Map<String, Object> jsonMap = new HashMap<>( );
+            jsonMap.put( "time_to_idle_seconds", 1600 );
+            jsonMap.put( "time_to_live_seconds", 12000 );
+            jsonMap.put( "max_entries_in_memory", 500 );
+            jsonMap.put( "max_entries_on_disk", 400 );
+
+            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonMap )
+                .put( "config/cache" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( response );
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .get( "config/cache" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( response );
+            CacheConfiguration config = response.getBody( ).jsonPath( ).getObject( "", CacheConfiguration.class );
+            assertEquals( 1600, config.getTimeToIdleSeconds( ) );
+            assertEquals( 12000, config.getTimeToLiveSeconds( ) );
+            assertEquals( 500, config.getMaxEntriesInMemory( ) );
+            assertEquals( 400, config.getMaxEntriesOnDisk( ) );
+        } finally
+        {
+            Map<String, Object> jsonMap = new HashMap<>( );
+            jsonMap.put( "time_to_idle_seconds", 1800 );
+            jsonMap.put( "time_to_live_seconds", 14400 );
+            jsonMap.put( "max_entries_in_memory", 1000 );
+            jsonMap.put( "max_entries_on_disk", 0 );
+
+            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonMap )
+                .put( "config/cache" )
+                .then( ).statusCode( 200 );
+
+        }
+    }
+
+
+    @Test
+    void testGetUserManagers() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .get( "user_managers" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+        List<BeanInformation> usrList = response.getBody( ).jsonPath( ).getList( "", BeanInformation.class );
+        assertEquals( 2, usrList.size( ) );
+        assertTrue( usrList.stream( ).anyMatch( bi -> "LDAP User Manager".equals( bi.getDisplayName( ) ) ) );
+        assertTrue( usrList.stream( ).anyMatch( bi -> "Database User Manager".equals( bi.getDisplayName( ) ) ) );
+    }
+
+    @Test
+    void testGetRbacManagers() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .get( "rbac_managers" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+        List<BeanInformation> rbacList = response.getBody( ).jsonPath( ).getList( "", BeanInformation.class );
+        assertEquals( 2, rbacList.size( ) );
+        assertTrue( rbacList.stream( ).anyMatch( bi -> "Database RBAC Manager".equals( bi.getDisplayName( ) ) ) );
+        assertTrue( rbacList.stream( ).anyMatch( bi -> "LDAP RBAC Manager".equals( bi.getDisplayName( ) ) ) );
+    }
+
+    @Test
+    void testUpdateConfiguration() {
+        String token = getAdminToken( );
+        try
+        {
+            Map<String, Object> jsonAsMap = new HashMap<>( );
+            jsonAsMap.put( "active_user_managers", Arrays.asList( "jpa", "ldap" ) );
+            jsonAsMap.put( "active_rbac_managers", Arrays.asList( "jpa" ) );
+            jsonAsMap.put( "user_cache_enabled", false );
+            jsonAsMap.put( "ldap_active", false );
+            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonAsMap )
+                .put( "config" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( response );
+
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .get( "config" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( response );
+            assertEquals( 2, response.getBody( ).jsonPath( ).getList( "active_user_managers" ).size( ) );
+        } finally
+        {
+            Map<String, Object> jsonAsMap = new HashMap<>( );
+            jsonAsMap.put( "active_user_managers", Arrays.asList( "jpa" ) );
+            jsonAsMap.put( "active_rbac_managers", Arrays.asList( "jpa" ) );
+            jsonAsMap.put( "user_cache_enabled", true );
+            jsonAsMap.put( "ldap_active", false );
+            given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonAsMap )
+                .put( "config" )
+                .then( ).statusCode( 200 );
+
+        }
+
+    }
+
+    @Test
+    void testGetConfigProperty() {
+        String token = getAdminToken( );
+        Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+            .when( )
+            .get( "config/properties/rest.csrffilter.absentorigin.deny" )
+            .then( ).statusCode( 200 ).extract( ).response( );
+        assertNotNull( response );
+        assertEquals( "true", response.getBody( ).jsonPath( ).getString( "value" ) );
+    }
+
+    @Test
+    void testUpdateConfigProperty() {
+        String token = getAdminToken( );
+
+        try
+        {
+            Map<String, String> jsonMap = new HashMap<>( );
+            jsonMap.put( "value", "false" );
+            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonMap )
+                .put( "config/properties/rest.csrffilter.absentorigin.deny" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( response );
+
+
+            response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .get( "config/properties/rest.csrffilter.absentorigin.deny" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+            assertNotNull( response );
+            assertEquals( "false", response.getBody( ).jsonPath( ).getString( "value" ) );
+        } finally
+        {
+            Map<String, String> jsonMap = new HashMap<>( );
+            jsonMap.put( "value", "true" );
+            Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+                .when( )
+                .body( jsonMap )
+                .put( "config/properties/rest.csrffilter.absentorigin.deny" )
+                .then( ).statusCode( 200 ).extract( ).response( );
+        }
+    }
+
+
+}