]> source.dussan.org Git - archiva.git/commitdiff
Refactoring of repository classes
authorMartin Stockhammer <martin_s@apache.org>
Fri, 2 Jul 2021 17:59:13 +0000 (19:59 +0200)
committerMartin Stockhammer <martin_s@apache.org>
Fri, 2 Jul 2021 17:59:13 +0000 (19:59 +0200)
70 files changed:
archiva-cli/src/main/java/org/apache/archiva/cli/ArchivaCli.java
archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ArchivaConfiguration.java
archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/java/RepositoryProviderMock.java
archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/java/SimpleArtifactConsumerTest.java
archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/ArtifactMissingChecksumsConsumerTest.java
archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java
archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
archiva-modules/archiva-base/archiva-consumers/archiva-indexer-consumers/src/test/java/org/apache/archiva/consumers/lucene/NexusIndexerConsumerTest.java
archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/AbstractRepositoryAdminTest.java
archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/group/RepositoryGroupAdminTest.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/CheckedResult.java [deleted file]
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryHandler.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/AbstractRepositoryValidator.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/CheckedResult.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/CombinedValidationResponse.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/CombinedValidator.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ErrorKeys.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/RepositoryChecker.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/RepositoryValidator.java
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ValidationResponse.java
archiva-modules/archiva-base/archiva-repository-layer/pom.xml
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractManagedRepository.java [deleted file]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRemoteRepository.java [deleted file]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepositoryGroup.java [deleted file]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/BasicManagedRepository.java [deleted file]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/BasicRemoteRepository.java [deleted file]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ConfigurationHandler.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/RepositoryGroupHandler.java [deleted file]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/AbstractRepositoryGroup.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/BasicRepositoryGroupValidator.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/RepositoryGroupHandler.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/AbstractManagedRepository.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/BasicManagedRepository.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/BasicManagedRepositoryValidator.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/ManagedRepositoryHandler.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/remote/AbstractRemoteRepository.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/remote/BasicRemoteRepository.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/validation/CommonGroupValidator.java [deleted file]
archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistryTest.java
archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/BasicManagedRepositoryValidatorTest.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/RepositoryContentConsumersTest.java
archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/RepositoryScannerTest.java
archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/MavenIndexManagerTest.java
archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/AbstractMavenRepositorySearch.java
archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchOSGITest.java
archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchPaginateTest.java
archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/AbstractProxyTestCase.java
archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/HttpProxyTransferTest.java
archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/MockConfiguration.java
archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven/MavenManagedRepository.java
archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven/MavenRemoteRepository.java
archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven/MavenRepositoryGroup.java
archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven/MavenRepositoryProvider.java
archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/metadata/storage/mock/MockConfiguration.java
archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/configuration/StubConfiguration.java
archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/configuration/TestConfiguration.java
archiva-modules/archiva-maven/archiva-maven-scheduler/src/test/java/org/apache/archiva/scheduler/indexing/maven/ArchivaIndexingTaskExecutorTest.java
archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/test/java/org/apache/archiva/scheduler/repository/AbstractArchivaRepositoryScanningTaskExecutorTest.java
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java
archiva-modules/archiva-web/archiva-rss/src/test/java/org/apache/archiva/rss/processor/NewVersionsOfArtifactRssFeedProcessorTest.java
archiva-modules/archiva-web/archiva-web-common/src/test/java/org/apache/archiva/web/rss/RssFeedServletTest.java
archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/AbstractRepositoryServletTestCase.java
archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/ArchivaDavResourceFactoryTest.java
archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/RepositoryServletSecurityTest.java
archiva-modules/plugins/problem-reports/src/test/java/org/apache/archiva/reports/consumers/DuplicateArtifactsConsumerTest.java

index 9204b4c8406a9408bc80b9001921d559769729a7..f8d901a1d3ec54415fc5ffa1af3c527a6d058c3e 100644 (file)
@@ -25,7 +25,7 @@ import org.apache.archiva.consumers.ConsumerException;
 import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
 import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
 import org.apache.archiva.consumers.RepositoryContentConsumer;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.scanner.RepositoryScanStatistics;
 import org.apache.archiva.repository.scanner.RepositoryScanner;
 import org.apache.archiva.repository.scanner.RepositoryScannerException;
@@ -36,8 +36,6 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
index f230257020ce62fc6e2f3d523cbe3cfc7150086e..cf90a13d3431a116f22ac32d89909b73e849f63c 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.archiva.configuration;
  * under the License.
  */
 
+import org.apache.archiva.components.registry.Registry;
 import org.apache.archiva.components.registry.RegistryException;
 import org.apache.archiva.components.registry.RegistryListener;
 
@@ -138,5 +139,11 @@ public interface ArchivaConfiguration
      * @return
      */
     public Path getDataDirectory();
+
+    /**
+     * Return the used configuration registry
+     * @return
+     */
+    Registry getRegistry( );
 }
 
index 8abed28c5730f241c98dd5e83204cb8676757485..10f9f2d45f3d2291710a7ee99e53c7c3fafaa200 100644 (file)
@@ -23,9 +23,8 @@ import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
 import org.apache.archiva.event.EventHandler;
-import org.apache.archiva.event.EventType;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
 import org.apache.archiva.repository.EditableManagedRepository;
 import org.apache.archiva.repository.EditableRemoteRepository;
 import org.apache.archiva.repository.RepositoryGroup;
index 2554a55835b233fc646fc43f68747fa31dab0ca6..dcb92399bf597c322378199b017b35404a3d5c8f 100644 (file)
@@ -21,7 +21,7 @@ package $package;
 
 import org.apache.archiva.metadata.repository.MetadataRepository;
 import org.apache.archiva.metadata.repository.RepositorySessionFactory;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.junit.Before;
index 27ad9680b471d7e8ae4fe7671fed343d5582e9b3..9fed19f2af507e8fee9efe46e133e7c045b4e069 100644 (file)
@@ -4,7 +4,7 @@ import org.apache.archiva.checksum.ChecksumAlgorithm;
 import org.apache.archiva.checksum.ChecksummedFile;
 import org.apache.archiva.common.utils.PathUtil;
 import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.EditableManagedRepository;
 import org.apache.commons.io.FileUtils;
 import org.assertj.core.api.Assertions;
index b2f66aa7f6793c27ab5831d2c6c101731d8d1293..ed42ef4755605005c4bd8cbaf5071c3b1a15c6b7 100644 (file)
@@ -24,11 +24,9 @@ import org.apache.archiva.metadata.repository.MetadataRepository;
 import org.apache.archiva.metadata.repository.RepositorySession;
 import org.apache.archiva.metadata.repository.RepositorySessionFactory;
 import org.apache.archiva.repository.ManagedRepositoryContent;
-import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.repository.maven.metadata.storage.Maven2RepositoryPathTranslator;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.ReleaseScheme;
 import org.apache.archiva.repository.RepositoryContentProvider;
 import org.apache.archiva.metadata.audit.RepositoryListener;
@@ -43,7 +41,6 @@ import org.junit.Before;
 import org.junit.runner.RunWith;
 import org.slf4j.LoggerFactory;
 import org.springframework.context.ApplicationContext;
-import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.ContextConfiguration;
 
 import javax.inject.Inject;
index d11008a687a968b87fc49f5628a5ca5ab679f0a3..0c8f71f14c1aad542fa6d90844218bbf147aff1b 100644 (file)
@@ -23,8 +23,8 @@ import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
 import org.apache.archiva.event.EventHandler;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
 import org.apache.archiva.repository.EditableManagedRepository;
 import org.apache.archiva.repository.EditableRemoteRepository;
 import org.apache.archiva.repository.EditableRepositoryGroup;
index 241eeb09bd00f59227c40a4660d42928aa767cf1..eb735e6fd4b62181e15c86b72479cb28ebdc4372 100644 (file)
@@ -25,9 +25,9 @@ import org.apache.archiva.configuration.ArchivaConfiguration;
 import org.apache.archiva.configuration.FileTypes;
 import org.apache.archiva.components.taskqueue.TaskQueueException;
 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.scheduler.ArchivaTaskScheduler;
 import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
index 993151a837ff6fd06f97ec440946fbdd88b9f851..406faf36ef30f8dce5ffcb3223889152c6bd8e45 100644 (file)
@@ -31,11 +31,10 @@ import org.apache.archiva.configuration.ArchivaConfiguration;
 import org.apache.archiva.redback.role.RoleManager;
 import org.apache.archiva.redback.users.User;
 import org.apache.archiva.redback.users.memory.SimpleUser;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
 import org.apache.commons.lang3.StringUtils;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.runner.RunWith;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 49fd38573345702d0e750275fb82def388475604..767c70ac876ecccd61daeb51eda0bf4f12d057ed 100644 (file)
@@ -26,7 +26,7 @@ import org.apache.archiva.admin.repository.AbstractRepositoryAdminTest;
 import org.apache.archiva.metadata.model.facets.AuditEvent;
 import org.apache.archiva.repository.Repository;
 import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.junit.Test;
 
 import javax.inject.Inject;
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/CheckedResult.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/CheckedResult.java
deleted file mode 100644 (file)
index 41961a5..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.apache.archiva.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.
- */
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-public interface CheckedResult<R extends Repository, D>
-{
-    R getRepository();
-
-    boolean isValid();
-
-    D getResult();
-
-}
index 4bb414cf8d32f6afec6ca201603f6f371fed90ed..5dbcfe5347fe3427f18efe0eccaef9d579906176 100644 (file)
@@ -18,8 +18,10 @@ package org.apache.archiva.repository;
  */
 
 import org.apache.archiva.configuration.Configuration;
+import org.apache.archiva.repository.validation.CheckedResult;
 import org.apache.archiva.repository.validation.RepositoryChecker;
 import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationResponse;
 
 import java.util.Collection;
 import java.util.Map;
@@ -165,6 +167,28 @@ public interface RepositoryHandler<R extends Repository, C>
      */
     RepositoryValidator<R> getValidator( );
 
+    /**
+     * Validates the set attributes of the given repository instance and returns the validation result.
+     * The repository registry uses all available validators and applies their validateRepository method to the given
+     * repository. Validation results will be merged per field.
+     *
+     * @param repository the repository to validate against
+     * @return the result of the validation.
+     */
+    ValidationResponse<R> validateRepository( R repository);
+
+    /**
+     * Validates the set attributes of the given repository instance for a repository update and returns the validation result.
+     * The repository registry uses all available validators and applies their validateRepositoryForUpdate method to the given
+     * repository. Validation results will be merged per field.
+     *
+     * @param repository the repository to validate against
+     * @return the result of the validation.
+     */
+    ValidationResponse<R> validateRepositoryForUpdate( R repository);
+
+
+
     /**
      * Returns <code>true</code>, if the repository is registered with the given id, otherwise <code>false</code>
      * @param id the repository identifier
index 2a521066662b72ce0e41b8302ccb836fe12fd9fc..ba96fe0b1fe486e56b9a34fec3f6a79193cfc1a7 100644 (file)
@@ -29,6 +29,7 @@ import org.apache.archiva.indexer.ArchivaIndexManager;
 import org.apache.archiva.indexer.IndexUpdateFailedException;
 import org.apache.archiva.repository.metadata.MetadataReader;
 import org.apache.archiva.repository.storage.StorageAsset;
+import org.apache.archiva.repository.validation.CheckedResult;
 import org.apache.archiva.repository.validation.ValidationError;
 import org.apache.archiva.repository.validation.ValidationResponse;
 
index 319fc50db3d2588322fb61f23a21207049cde1a5..ae45419a1ef5c6abfcb2361b160f8588c78b51dd 100644 (file)
@@ -17,16 +17,26 @@ package org.apache.archiva.repository.validation;
  * under the License.
  */
 
-import org.apache.archiva.repository.CheckedResult;
 import org.apache.archiva.repository.Repository;
 import org.apache.archiva.repository.RepositoryRegistry;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * @author Martin Stockhammer <martin_s@apache.org>
  */
 public abstract class AbstractRepositoryValidator<R extends Repository> implements RepositoryValidator<R>
 {
     protected RepositoryRegistry repositoryRegistry;
+    private final String category;
+
+    public AbstractRepositoryValidator( String category )
+    {
+        this.category = category;
+    }
 
     @Override
     public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
@@ -34,6 +44,23 @@ public abstract class AbstractRepositoryValidator<R extends Repository> implemen
         this.repositoryRegistry = repositoryRegistry;
     }
 
+    protected String getCategory() {
+        return this.category;
+    }
+
+
+
+    protected Map<String, List<ValidationError>> appendError( Map<String, List<ValidationError>> errorMap, String attribute, String type, Object... parameter )
+    {
+        String errorKey = getCategory( ) + "." + attribute + "." + type;
+        Map<String, List<ValidationError>> result;
+        result = errorMap == null ? new HashMap<>( ) : errorMap;
+        ValidationError error = ValidationError.ofKey( errorKey, parameter );
+        List<ValidationError> errList = result.computeIfAbsent( error.getAttribute( ), k -> new ArrayList<>( ) );
+        errList.add( error );
+        return result;
+    }
+
     protected abstract ValidationResponse<R> apply( R repo, boolean update );
 
     @Override
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/CheckedResult.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/CheckedResult.java
new file mode 100644 (file)
index 0000000..ebc10e8
--- /dev/null
@@ -0,0 +1,33 @@
+package org.apache.archiva.repository.validation;
+/*
+ * 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;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public interface CheckedResult<R extends Repository, D>
+{
+    R getRepository();
+
+    boolean isValid();
+
+    D getResult();
+
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/CombinedValidationResponse.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/CombinedValidationResponse.java
new file mode 100644 (file)
index 0000000..3883077
--- /dev/null
@@ -0,0 +1,74 @@
+package org.apache.archiva.repository.validation;
+/*
+ * 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.commons.lang3.StringUtils;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class CombinedValidationResponse<R extends Repository> implements CheckedResult<R, Map<String, List<ValidationError>>>
+{
+
+    private final Map<String, List<ValidationError>> errorMap = new HashMap<>( );
+    private final R repository;
+
+    public CombinedValidationResponse( R repository )
+    {
+        this.repository = repository;
+    }
+
+    @Override
+    public R getRepository( )
+    {
+        return repository;
+    }
+
+    @Override
+    public boolean isValid( )
+    {
+        return errorMap.size()==0;
+    }
+
+    @Override
+    public Map<String, List<ValidationError>> getResult( )
+    {
+        return errorMap;
+    }
+
+    public void addErrors(String key, List<ValidationError> errorList) {
+        if ( StringUtils.isNotEmpty( key ) && errorList!=null && errorList.size()>0) {
+            this.errorMap.put( key, errorList );
+        }
+    }
+
+    public void addErrors(Map<String, List<ValidationError>> errorMap) {
+        if (errorMap!=null) {
+            errorMap.entrySet( ).stream( ).forEach( e -> addErrors( e.getKey( ), e.getValue( ) ) );
+        }
+    }
+
+    public void addResult(CheckedResult<R, Map<String, List<ValidationError>>> result) {
+        this.addErrors( result.getResult( ) );
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/CombinedValidator.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/CombinedValidator.java
new file mode 100644 (file)
index 0000000..a0dd444
--- /dev/null
@@ -0,0 +1,87 @@
+package org.apache.archiva.repository.validation;
+/*
+ * 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.RepositoryRegistry;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A combined validator cumulates the validation results of multiple validators
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class CombinedValidator<R extends Repository>
+implements RepositoryValidator<R> {
+
+    private final List<RepositoryValidator<R>> validatorList;
+    private final Class<R> flavourClazz;
+
+    public CombinedValidator( Class<R> flavourClazz, List<RepositoryValidator<R>> validatorList )
+    {
+        if (flavourClazz==null) {
+            throw new IllegalArgumentException( "The flavour class may not be null" );
+        }
+        this.flavourClazz = flavourClazz;
+        if (validatorList==null) {
+            throw new IllegalArgumentException( "The validator list may not be null" );
+        }
+        this.validatorList = validatorList;
+    }
+
+    @Override
+    public CheckedResult<R, Map<String, List<ValidationError>>> apply( R r )
+    {
+        CombinedValidationResponse<R> response = new CombinedValidationResponse<>( r );
+        validatorList.stream( ).forEach(
+            v -> response.addResult( v.apply( r ) )
+        );
+        return response;
+    }
+
+    @Override
+    public CheckedResult<R, Map<String, List<ValidationError>>> applyForUpdate( R repo )
+    {
+        CombinedValidationResponse<R> response = new CombinedValidationResponse<>( repo );
+        validatorList.stream( ).forEach(
+            v -> response.addResult( v.applyForUpdate( repo ) )
+        );
+        return response;
+
+    }
+
+    @Override
+    public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
+    {
+        // Not used
+    }
+
+    @Override
+    public Class<R> getFlavour( )
+    {
+        return flavourClazz;
+    }
+
+    @Override
+    public boolean isFlavour( Class<?> clazz )
+    {
+        return flavourClazz.isAssignableFrom( clazz );
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ErrorKeys.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ErrorKeys.java
new file mode 100644 (file)
index 0000000..315d4df
--- /dev/null
@@ -0,0 +1,38 @@
+package org.apache.archiva.repository.validation;
+/*
+ * 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.registry.Registry;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public interface ErrorKeys
+{
+    String ISNULL = "isnull";
+    String ISEMPTY = "empty";
+    String EXISTS = "exists";
+    String MANAGED_REPOSITORY_EXISTS = "managed_repo_exists";
+    String REMOTE_REPOSITORY_EXISTS = "remote_repo_exists";
+    String REPOSITORY_GROUP_EXISTS = "group_exists";
+    String MAX_LENGTH_EXCEEDED = "max_length";
+    String INVALID_CHARS = "invalid_chars";
+    String BELOW_MIN = "min";
+    String INVALID_SCHEDULING_EXPRESSION = "scheduling_exp_invalid";
+    String INVALID_LOCATION = "location_invalid";
+}
index f208d10fe2243a4c3a930a0581d78767b4f709c6..28972491fe41eab1e048f21ef9158966b48c8ff3 100644 (file)
@@ -17,11 +17,9 @@ package org.apache.archiva.repository.validation;
  * under the License.
  */
 
-import org.apache.archiva.repository.CheckedResult;
 import org.apache.archiva.repository.Repository;
 
 import java.util.function.Function;
-import java.util.function.Predicate;
 
 /**
  * @author Martin Stockhammer <martin_s@apache.org>
index 041fe8a482a325c9d0f6c918ecfce12db6e054b1..25382b31bcfabc410ae845f2c2c45a27230bc648 100644 (file)
@@ -33,6 +33,11 @@ import java.util.function.Function;
 public interface RepositoryValidator<R extends Repository> extends RepositoryChecker<R, Map<String, List<ValidationError>>>, Comparable<RepositoryValidator<R>>
 {
 
+    String REPOSITORY_ID_VALID_EXPRESSION = "^[a-zA-Z0-9._-]+$";
+    String REPOSITORY_NAME_VALID_EXPRESSION = "^([a-zA-Z0-9.)/_(-]|\\s)+$";
+    String REPOSITORY_LOCATION_VALID_EXPRESSION = "^[-a-zA-Z0-9._/~:?!&amp;=\\\\]+$";
+
+
     int DEFAULT_PRIORITY=1000;
 
     /**
@@ -81,5 +86,16 @@ public interface RepositoryValidator<R extends Repository> extends RepositoryChe
 
     Class<R> getFlavour();
 
-    boolean isFlavour(Class<?> clazz);
+    default boolean isFlavour(Class<?> clazz) {
+        return getFlavour( ).isAssignableFrom( clazz );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    default <RR extends Repository> RepositoryValidator<RR> narrowTo( Class<RR> clazz ) {
+        if (isFlavour( clazz )) {
+            return (RepositoryValidator<RR>) this;
+        } else {
+            throw new IllegalArgumentException( "Could not narrow to " + clazz );
+        }
+    }
 }
index 377a3ccb2438aaefebfe2fa80d517674c1ccf85f..f52db1fc71fd363ef6de10e0e8f0f7543d493438 100644 (file)
@@ -17,7 +17,6 @@ package org.apache.archiva.repository.validation;
  * under the License.
  */
 
-import org.apache.archiva.repository.CheckedResult;
 import org.apache.archiva.repository.Repository;
 
 import java.util.ArrayList;
@@ -25,7 +24,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Function;
 
 /**
  * A validation response gives information about the validation status for certain attributes.
index 496450386ec7ad225a4c3efefc143560e1013e93..877487935c63d450be00e35c31b1adf1c186ddec 100644 (file)
       <groupId>org.apache.archiva.components.registry</groupId>
       <artifactId>archiva-components-spring-registry-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.archiva.components</groupId>
+      <artifactId>archiva-components-spring-quartz</artifactId>
+    </dependency>
     <dependency>
       <groupId>com.cronutils</groupId>
       <artifactId>cron-utils</artifactId>
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractManagedRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractManagedRepository.java
deleted file mode 100644 (file)
index 57ce041..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.apache.archiva.repository.base;
-
-/*
- * 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.EditableManagedRepository;
-import org.apache.archiva.repository.ManagedRepositoryContent;
-import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.storage.RepositoryStorage;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Simple implementation of a managed repository.
- */
-public abstract class AbstractManagedRepository extends AbstractRepository implements EditableManagedRepository
-{
-    private boolean blocksRedeployment = false;
-    private ManagedRepositoryContent content;
-    private Set<ReleaseScheme> activeReleaseSchemes = new HashSet<>(  );
-    private Set<ReleaseScheme> uActiveReleaseSchemes = Collections.unmodifiableSet( activeReleaseSchemes );
-
-    public AbstractManagedRepository( RepositoryType type, String id, String name, RepositoryStorage storage)
-    {
-        super( type, id, name, storage );
-    }
-
-    public AbstractManagedRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
-    {
-        super( primaryLocale, type, id, name, storage );
-    }
-
-    @Override
-    public ManagedRepositoryContent getContent( )
-    {
-        return content;
-    }
-
-    @Override
-    public void setContent( ManagedRepositoryContent content) {
-        this.content = content;
-    }
-
-    @Override
-    public void setBlocksRedeployment( boolean blocksRedeployment )
-    {
-        this.blocksRedeployment = blocksRedeployment;
-    }
-
-    @Override
-    public boolean blocksRedeployments( )
-    {
-        return blocksRedeployment;
-    }
-
-    @Override
-    public Set<ReleaseScheme> getActiveReleaseSchemes( )
-    {
-        return uActiveReleaseSchemes;
-    }
-
-    @Override
-    public void addActiveReleaseScheme( ReleaseScheme scheme )
-    {
-        this.activeReleaseSchemes.add(scheme);
-    }
-
-    @Override
-    public void removeActiveReleaseScheme( ReleaseScheme scheme )
-    {
-        this.activeReleaseSchemes.remove(scheme);
-    }
-
-    @Override
-    public void clearActiveReleaseSchemes( )
-    {
-        this.activeReleaseSchemes.clear();
-    }
-
-
-}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRemoteRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRemoteRepository.java
deleted file mode 100644 (file)
index 51d7a98..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-package org.apache.archiva.repository.base;
-
-/*
- * 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.EditableRemoteRepository;
-import org.apache.archiva.repository.RemoteRepositoryContent;
-import org.apache.archiva.repository.RepositoryCredentials;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.storage.RepositoryStorage;
-
-import java.net.URI;
-import java.time.Duration;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Abstract implementation of a remote repository. Abstract classes must implement the
- * features and capabilities by themselves.
- */
-public abstract class AbstractRemoteRepository extends AbstractRepository implements EditableRemoteRepository
-{
-
-    private RepositoryCredentials credentials;
-    private String checkPath;
-    private Map<String,String> extraParameters = new HashMap<>(  );
-    private Map<String,String> uExtraParameters = Collections.unmodifiableMap( extraParameters );
-    private Map<String,String> extraHeaders = new HashMap<>(  );
-    private Map<String,String> uExtraHeaders = Collections.unmodifiableMap( extraHeaders );
-    private Duration timeout = Duration.ofSeconds( 60 );
-    private String proxyId;
-    private RemoteRepositoryContent content;
-
-    public AbstractRemoteRepository( RepositoryType type, String id, String name , RepositoryStorage storage)
-    {
-        super( type, id, name, storage );
-    }
-
-    public AbstractRemoteRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
-    {
-        super( primaryLocale, type, id, name, storage );
-    }
-
-    @Override
-    public void setCredentials( RepositoryCredentials credentials )
-    {
-        this.credentials = credentials;
-    }
-
-    @Override
-    public void setCheckPath( String path )
-    {
-        this.checkPath = path;
-    }
-
-    @Override
-    public void setExtraParameters( Map<String, String> params )
-    {
-        this.extraParameters.clear();
-        this.extraParameters.putAll(params);
-    }
-
-    @Override
-    public void addExtraParameter( String key, String value )
-    {
-        this.extraParameters.put(key, value);
-    }
-
-    @Override
-    public void setExtraHeaders( Map<String, String> headers )
-    {
-        this.extraHeaders.clear();
-        this.extraHeaders.putAll(headers);
-    }
-
-    @Override
-    public void addExtraHeader( String header, String value )
-    {
-        this.extraHeaders.put(header, value);
-    }
-
-    @Override
-    public void setTimeout( Duration duration )
-    {
-        this.timeout = duration;
-    }
-
-    @Override
-    public RemoteRepositoryContent getContent( )
-    {
-        return content;
-    }
-
-    @Override
-    public void setContent(RemoteRepositoryContent content) {
-        this.content = content;
-    }
-
-    @Override
-    public RepositoryCredentials getLoginCredentials( )
-    {
-        return credentials;
-    }
-
-    @Override
-    public String getCheckPath( )
-    {
-        return checkPath;
-    }
-
-    @Override
-    public Map<String, String> getExtraParameters( )
-    {
-        return uExtraParameters;
-    }
-
-    @Override
-    public Map<String, String> getExtraHeaders( )
-    {
-        return uExtraHeaders;
-    }
-
-    @Override
-    public Duration getTimeout( )
-    {
-        return timeout;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder str = new StringBuilder();
-        return str.append("checkPath=").append(checkPath)
-                .append(",creds:").append(credentials).toString();
-    }
-
-    @Override
-    public void setLocation(URI location) {
-        // Location of remote repositories is not for the local filestore
-        super.location = location;
-    }
-}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepositoryGroup.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepositoryGroup.java
deleted file mode 100644 (file)
index 155e575..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.apache.archiva.repository.base;
-
-/*
- * 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.EditableRepositoryGroup;
-import org.apache.archiva.repository.ManagedRepository;
-import org.apache.archiva.repository.RepositoryCapabilities;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.storage.RepositoryStorage;
-import org.apache.commons.collections4.map.ListOrderedMap;
-
-import java.util.List;
-import java.util.Locale;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-/**
- * Abstract repository group implementation.
- *
- */
-public class AbstractRepositoryGroup extends AbstractRepository implements EditableRepositoryGroup
-{
-
-    private ListOrderedMap<String, ManagedRepository> repositories = new ListOrderedMap<>();
-
-    private int mergedIndexTTL;
-
-    private final ReadWriteLock rwl = new ReentrantReadWriteLock();
-
-    private RepositoryCapabilities capabilities;
-
-    public AbstractRepositoryGroup( RepositoryType type, String id, String name, RepositoryStorage storage) {
-        super(type, id, name, storage);
-    }
-
-    public AbstractRepositoryGroup(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage) {
-        super(primaryLocale, type, id, name, storage);
-    }
-
-    @Override
-    public boolean hasIndex() {
-        return true;
-    }
-
-    @Override
-    public RepositoryCapabilities getCapabilities() {
-        return capabilities;
-    }
-
-
-    @Override
-    public void clearRepositories() {
-        rwl.writeLock().lock();
-        try {
-            repositories.clear();
-        } finally {
-            rwl.writeLock().unlock();
-        }
-    }
-
-    @Override
-    public void setRepositories(List<ManagedRepository> newRepositories) {
-        rwl.writeLock().lock();
-        try {
-            repositories.clear();
-            for(ManagedRepository repo : newRepositories) {
-                if (repo!=null)
-                    repositories.put(repo.getId(), repo);
-            }
-        } finally {
-            rwl.writeLock().unlock();
-        }
-    }
-
-    @Override
-    public void addRepository(ManagedRepository repository) {
-        rwl.writeLock().lock();
-        try {
-            if (repository!=null)
-                repositories.put(repository.getId(), repository);
-        } finally {
-            rwl.writeLock().unlock();
-        }
-    }
-
-    @Override
-    public void addRepository(int index, ManagedRepository repository) {
-        rwl.writeLock().lock();
-        try {
-            if (repository!=null)
-                repositories.put(index, repository.getId(), repository);
-        } finally {
-            rwl.writeLock().unlock();
-        }
-    }
-
-    @Override
-    public boolean removeRepository(ManagedRepository repository) {
-        rwl.writeLock().lock();
-        try {
-            return repositories.remove(repository.getId(), repository);
-        } finally {
-            rwl.writeLock().unlock();
-        }
-    }
-
-    @Override
-    public ManagedRepository removeRepository(String repoId) {
-        rwl.writeLock().lock();
-        try {
-            return repositories.remove(repoId);
-        } finally {
-            rwl.writeLock().unlock();
-        }
-    }
-
-    @Override
-    public void setMergedIndexTTL(int timeInSeconds) {
-        this.mergedIndexTTL = timeInSeconds;
-    }
-
-    @Override
-    public List<ManagedRepository> getRepositories() {
-        rwl.readLock().lock();
-        try {
-            return repositories.valueList();
-        } finally {
-            rwl.readLock().unlock();
-        }
-    }
-
-    @Override
-    public boolean contains(ManagedRepository repository) {
-        rwl.readLock().lock();
-        try {
-            return repositories.containsValue(repository);
-        } finally {
-            rwl.readLock().unlock();
-        }
-    }
-
-    @Override
-    public boolean contains(String id) {
-        rwl.readLock().lock();
-        try {
-            return repositories.containsKey(id);
-        } finally {
-            rwl.readLock().unlock();
-        }
-    }
-
-    @Override
-    public int getMergedIndexTTL() {
-        return mergedIndexTTL;
-    }
-
-    protected void setCapabilities(RepositoryCapabilities capabilities) {
-        this.capabilities = capabilities;
-    }
-}
index d3eb836c2ef8c3f50e6a33ba4d3ca95d96ab81ea..34a4f956c73276896158de795b68e00c9a8d960e 100644 (file)
@@ -38,7 +38,8 @@ import org.apache.archiva.indexer.ArchivaIndexingContext;
 import org.apache.archiva.indexer.IndexCreationFailedException;
 import org.apache.archiva.indexer.IndexManagerFactory;
 import org.apache.archiva.indexer.IndexUpdateFailedException;
-import org.apache.archiva.repository.CheckedResult;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
+import org.apache.archiva.repository.validation.CheckedResult;
 import org.apache.archiva.repository.EditableManagedRepository;
 import org.apache.archiva.repository.EditableRemoteRepository;
 import org.apache.archiva.repository.EditableRepository;
@@ -52,7 +53,6 @@ import org.apache.archiva.repository.RepositoryProvider;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.RepositoryType;
 import org.apache.archiva.repository.UnsupportedRepositoryTypeException;
-import org.apache.archiva.repository.base.validation.CommonGroupValidator;
 import org.apache.archiva.repository.event.LifecycleEvent;
 import org.apache.archiva.repository.event.RepositoryEvent;
 import org.apache.archiva.repository.event.RepositoryIndexEvent;
@@ -61,7 +61,6 @@ import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.StagingRepositoryFeature;
 import org.apache.archiva.repository.metadata.MetadataReader;
 import org.apache.archiva.repository.storage.StorageAsset;
-import org.apache.archiva.repository.validation.RepositoryChecker;
 import org.apache.archiva.repository.validation.RepositoryValidator;
 import org.apache.archiva.repository.validation.ValidationError;
 import org.apache.archiva.repository.validation.ValidationResponse;
@@ -240,7 +239,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa
     }
 
 
-    protected Map<RepositoryType, RepositoryProvider> getRepositoryProviderMap( )
+    public Map<RepositoryType, RepositoryProvider> getRepositoryProviderMap( )
     {
         Map<RepositoryType, RepositoryProvider> map = new HashMap<>( );
         if ( repositoryProviders != null )
@@ -256,7 +255,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa
         return map;
     }
 
-    protected RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
+    public RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
     {
         return repositoryProviders.stream( ).filter( repositoryProvider -> repositoryProvider.provides( ).contains( type ) ).findFirst( ).orElseThrow( ( ) -> new RepositoryException( "Repository type cannot be handled: " + type ) );
     }
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/BasicManagedRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/BasicManagedRepository.java
deleted file mode 100644 (file)
index a82fd77..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.apache.archiva.repository.base;
-
-/*
- * 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.common.filelock.DefaultFileLockManager;
-import org.apache.archiva.common.filelock.FileLockManager;
-import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.RepositoryCapabilities;
-import org.apache.archiva.repository.RepositoryRequestInfo;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.StandardCapabilities;
-import org.apache.archiva.repository.storage.StorageAsset;
-import org.apache.archiva.repository.storage.fs.FilesystemStorage;
-import org.apache.archiva.repository.storage.RepositoryStorage;
-import org.apache.archiva.repository.features.ArtifactCleanupFeature;
-import org.apache.archiva.repository.features.IndexCreationFeature;
-import org.apache.archiva.repository.features.StagingRepositoryFeature;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Locale;
-
-/**
- *
- * Just a helper class, mainly used for unit tests.
- *
- *
- */
-public class BasicManagedRepository extends AbstractManagedRepository
-
-{
-    Logger log = LoggerFactory.getLogger(BasicManagedRepository.class);
-    ArtifactCleanupFeature artifactCleanupFeature = new ArtifactCleanupFeature(  );
-    StagingRepositoryFeature stagingRepositoryFeature = new StagingRepositoryFeature( );
-
-    static final StandardCapabilities CAPABILITIES = new StandardCapabilities( new ReleaseScheme[] {
-        ReleaseScheme.RELEASE, ReleaseScheme.SNAPSHOT
-    }, new String[] {"default"}, new String[0], new String[] {
-        ArtifactCleanupFeature.class.toString(), IndexCreationFeature.class.toString(),
-        StagingRepositoryFeature.class.toString()
-    }, true, true, true, true, true  );
-
-    public BasicManagedRepository( String id, String name, RepositoryStorage repositoryStorage )
-    {
-        super( RepositoryType.MAVEN, id, name, repositoryStorage );
-        initFeatures();
-    }
-
-    public BasicManagedRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage )
-    {
-        super( primaryLocale, type, id, name, repositoryStorage);
-        initFeatures();
-    }
-
-    private void initFeatures() {
-        IndexCreationFeature indexCreationFeature = new IndexCreationFeature(this, this);
-        addFeature( artifactCleanupFeature );
-        addFeature( indexCreationFeature );
-        addFeature( stagingRepositoryFeature );
-    }
-
-    @Override
-    public boolean hasIndex( )
-    {
-        return true;
-    }
-
-    @Override
-    public RepositoryCapabilities getCapabilities( )
-    {
-        return CAPABILITIES;
-    }
-
-
-    @Override
-    public RepositoryRequestInfo getRequestInfo() {
-        return null;
-    }
-
-    /**
-     * Creates a filesystem based repository instance. The path is built by basePath/repository-id
-     *
-     * @param id The repository id
-     * @param name The name of the repository
-     * @param repositoryPath The path to the repository
-     * @return The repository instance
-     * @throws IOException
-     */
-    public static BasicManagedRepository newFilesystemInstance(String id, String name, Path repositoryPath) throws IOException {
-        FileLockManager lockManager = new DefaultFileLockManager();
-        FilesystemStorage storage = new FilesystemStorage(repositoryPath, lockManager);
-        return new BasicManagedRepository(id, name, storage);
-    }
-
-}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/BasicRemoteRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/BasicRemoteRepository.java
deleted file mode 100644 (file)
index afec070..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.apache.archiva.repository.base;
-
-/*
- * 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.common.filelock.DefaultFileLockManager;
-import org.apache.archiva.common.filelock.FileLockManager;
-import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.RepositoryCapabilities;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.StandardCapabilities;
-import org.apache.archiva.repository.storage.fs.FilesystemStorage;
-import org.apache.archiva.repository.storage.RepositoryStorage;
-import org.apache.archiva.repository.features.IndexCreationFeature;
-import org.apache.archiva.repository.features.RemoteIndexFeature;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Locale;
-
-/**
- *
- * Just a helper class, mainly used for unit tests.
- *
- *
- */
-public class BasicRemoteRepository extends AbstractRemoteRepository
-
-{
-    Logger log = LoggerFactory.getLogger(BasicRemoteRepository.class);
-
-    RemoteIndexFeature remoteIndexFeature = new RemoteIndexFeature();
-    IndexCreationFeature indexCreationFeature = new IndexCreationFeature(true);
-
-
-    static final StandardCapabilities CAPABILITIES = new StandardCapabilities( new ReleaseScheme[] {
-        ReleaseScheme.RELEASE, ReleaseScheme.SNAPSHOT
-    }, new String[] {"default"}, new String[0], new String[] {
-        RemoteIndexFeature.class.toString(),
-            IndexCreationFeature.class.toString()
-    }, true, true, true, true, true  );
-
-    public BasicRemoteRepository( String id, String name, RepositoryStorage storage)
-    {
-        super( RepositoryType.MAVEN, id, name, storage);
-        initFeatures();
-    }
-
-    public BasicRemoteRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
-    {
-        super( primaryLocale, type, id, name, storage );
-        initFeatures();
-    }
-
-    private void initFeatures() {
-        addFeature( remoteIndexFeature );
-        addFeature( indexCreationFeature );
-    }
-
-    @Override
-    public boolean hasIndex( )
-    {
-        return true;
-    }
-
-    @Override
-    public RepositoryCapabilities getCapabilities( )
-    {
-        return CAPABILITIES;
-    }
-
-
-    public static BasicRemoteRepository newFilesystemInstance(String id, String name, Path basePath) throws IOException {
-        FileLockManager lockManager = new DefaultFileLockManager();
-        FilesystemStorage storage = new FilesystemStorage(basePath.resolve(id), lockManager);
-        return new BasicRemoteRepository(id, name, storage);
-    }
-}
index 4c21083e9c852ff18d6c50f110ad61554a00979f..9278e022a085cd42b6fcdb3455d0df8279c71172 100644 (file)
@@ -72,7 +72,7 @@ public class ConfigurationHandler
         archivaConfiguration.save( configuration, "" );
     }
 
-    ReentrantReadWriteLock getLock() {
+    public ReentrantReadWriteLock getLock() {
         return lock;
     }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/RepositoryGroupHandler.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/RepositoryGroupHandler.java
deleted file mode 100644 (file)
index 8604ba9..0000000
+++ /dev/null
@@ -1,598 +0,0 @@
-package org.apache.archiva.repository.base;
-/*
- * 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.registry.RegistryException;
-import org.apache.archiva.configuration.Configuration;
-import org.apache.archiva.configuration.IndeterminateConfigurationException;
-import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
-import org.apache.archiva.configuration.RepositoryGroupConfiguration;
-import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler;
-import org.apache.archiva.repository.CheckedResult;
-import org.apache.archiva.repository.EditableRepository;
-import org.apache.archiva.repository.EditableRepositoryGroup;
-import org.apache.archiva.repository.ManagedRepository;
-import org.apache.archiva.repository.RepositoryException;
-import org.apache.archiva.repository.RepositoryGroup;
-import org.apache.archiva.repository.RepositoryHandler;
-import org.apache.archiva.repository.RepositoryProvider;
-import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.event.RepositoryEvent;
-import org.apache.archiva.repository.features.IndexCreationFeature;
-import org.apache.archiva.repository.storage.StorageAsset;
-import org.apache.archiva.repository.validation.RepositoryChecker;
-import org.apache.archiva.repository.validation.RepositoryValidator;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Named;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.stream.Collectors;
-
-import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
-
-/**
- * This class manages repository groups for the RepositoryRegistry.
- * It is tightly coupled with the {@link ArchivaRepositoryRegistry}.
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Service( "repositoryGroupHandler#default" )
-public class RepositoryGroupHandler implements RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration>
-{
-    private static final Logger log = LoggerFactory.getLogger( RepositoryGroupHandler.class );
-
-    private final ArchivaRepositoryRegistry repositoryRegistry;
-    private final ConfigurationHandler configurationHandler;
-    private final MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
-
-    private final Map<String, RepositoryGroup> repositoryGroups = new HashMap<>( );
-    private final RepositoryValidator<RepositoryGroup> validator;
-
-    private Path groupsDirectory;
-
-
-    /**
-     * Creates a new instance. All dependencies are injected on the constructor.
-     *
-     * @param repositoryRegistry           the registry. To avoid circular dependencies via DI, this class registers itself on the registry.
-     * @param configurationHandler         the configuration handler is used to retrieve and save configuration.
-     * @param mergedRemoteIndexesScheduler the index scheduler is used for merging the indexes from all group members
-     */
-    public RepositoryGroupHandler( ArchivaRepositoryRegistry repositoryRegistry,
-                                   ConfigurationHandler configurationHandler,
-                                   @Named( "mergedRemoteIndexesScheduler#default" ) MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler,
-                                   @Named( "repositoryValidator#common#group") RepositoryValidator<RepositoryGroup> repositoryGroupValidator
-                                   )
-    {
-        this.configurationHandler = configurationHandler;
-        this.mergedRemoteIndexesScheduler = mergedRemoteIndexesScheduler;
-        this.repositoryRegistry = repositoryRegistry;
-        this.validator = repositoryGroupValidator;
-    }
-
-    @Override
-    @PostConstruct
-    public void init( )
-    {
-        log.debug( "Initializing repository group handler " + repositoryRegistry.toString( ) );
-        initializeStorage( );
-        // We are registering this class on the registry. This is necessary to avoid circular dependencies via injection.
-        this.repositoryRegistry.registerGroupHandler( this );
-    }
-
-    public void initializeFromConfig( )
-    {
-        this.repositoryGroups.clear( );
-        this.repositoryGroups.putAll( newInstancesFromConfig( ) );
-        for ( RepositoryGroup group : this.repositoryGroups.values( ) )
-        {
-            initializeGroup( group );
-        }
-    }
-
-    private void initializeStorage( )
-    {
-        Path baseDir = this.configurationHandler.getArchivaConfiguration( ).getRepositoryGroupBaseDir( );
-        if ( !Files.exists( baseDir ) )
-        {
-            try
-            {
-                Files.createDirectories( baseDir );
-            }
-            catch ( IOException e )
-            {
-                log.error( "Could not create group base directory: {}", e.getMessage( ), e );
-            }
-        }
-        this.groupsDirectory = baseDir;
-    }
-
-    private void initializeGroup( RepositoryGroup repositoryGroup )
-    {
-        StorageAsset indexDirectory = getMergedIndexDirectory( repositoryGroup );
-        if ( !indexDirectory.exists( ) )
-        {
-            try
-            {
-                indexDirectory.create( );
-            }
-            catch ( IOException e )
-            {
-                log.error( "Could not create index directory {} for group {}: {}", indexDirectory, repositoryGroup.getId( ), e.getMessage( ) );
-            }
-        }
-        Path groupPath = groupsDirectory.resolve( repositoryGroup.getId( ) );
-        if ( !Files.exists( groupPath ) )
-        {
-            try
-            {
-                Files.createDirectories( groupPath );
-            }
-            catch ( IOException e )
-            {
-                log.error( "Could not create repository group directory {}", groupPath );
-            }
-        }
-        mergedRemoteIndexesScheduler.schedule( repositoryGroup,
-            indexDirectory );
-    }
-
-    public StorageAsset getMergedIndexDirectory( RepositoryGroup group )
-    {
-        if ( group != null )
-        {
-            return group.getFeature( IndexCreationFeature.class ).get( ).getLocalIndexPath( );
-        }
-        else
-        {
-            return null;
-        }
-    }
-
-
-    @Override
-    public Map<String, RepositoryGroup> newInstancesFromConfig( )
-    {
-        try
-        {
-            List<RepositoryGroupConfiguration> repositoryGroupConfigurations =
-                this.configurationHandler.getBaseConfiguration( ).getRepositoryGroups( );
-
-            if ( repositoryGroupConfigurations == null )
-            {
-                return Collections.emptyMap( );
-            }
-
-            Map<String, RepositoryGroup> repositoryGroupMap = new LinkedHashMap<>( repositoryGroupConfigurations.size( ) );
-
-            Map<RepositoryType, RepositoryProvider> providerMap = repositoryRegistry.getRepositoryProviderMap( );
-            for ( RepositoryGroupConfiguration repoConfig : repositoryGroupConfigurations )
-            {
-                RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
-                if ( providerMap.containsKey( repositoryType ) )
-                {
-                    try
-                    {
-                        RepositoryGroup repo = createNewRepositoryGroup( providerMap.get( repositoryType ), repoConfig );
-                        repositoryGroupMap.put( repo.getId( ), repo );
-                    }
-                    catch ( Exception e )
-                    {
-                        log.error( "Could not create repository group {}: {}", repoConfig.getId( ), e.getMessage( ), e );
-                    }
-                }
-            }
-            return repositoryGroupMap;
-        }
-        catch ( Throwable e )
-        {
-            log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
-            return Collections.emptyMap( );
-        }
-    }
-
-    @Override
-    public RepositoryGroup newInstance( final RepositoryType type, String id ) throws RepositoryException
-    {
-        RepositoryProvider provider = repositoryRegistry.getProvider( type );
-        RepositoryGroupConfiguration config = new RepositoryGroupConfiguration( );
-        config.setId( id );
-        return createNewRepositoryGroup( provider, config );
-    }
-
-    @Override
-    public RepositoryGroup newInstance( final RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException
-    {
-        RepositoryType type = RepositoryType.valueOf( repositoryConfiguration.getType( ) );
-        RepositoryProvider provider = repositoryRegistry.getProvider( type );
-        return createNewRepositoryGroup( provider, repositoryConfiguration );
-    }
-
-    private RepositoryGroup createNewRepositoryGroup( RepositoryProvider provider, RepositoryGroupConfiguration config ) throws RepositoryException
-    {
-        RepositoryGroup repositoryGroup = provider.createRepositoryGroup( config );
-        updateReferences( repositoryGroup, config );
-        return repositoryGroup;
-    }
-
-
-    /**
-     * Adds a new repository group to the current list, or replaces the repository group definition with
-     * the same id, if it exists already.
-     * The change is saved to the configuration immediately.
-     *
-     * @param repositoryGroup the new repository group.
-     * @throws RepositoryException if the new repository group could not be saved to the configuration.
-     */
-    @Override
-    public RepositoryGroup put( final RepositoryGroup repositoryGroup ) throws RepositoryException
-    {
-        final String id = repositoryGroup.getId( );
-        RepositoryGroup originRepoGroup = repositoryGroups.remove( id );
-        try
-        {
-            if ( originRepoGroup != null && originRepoGroup != repositoryGroup )
-            {
-                this.mergedRemoteIndexesScheduler.unschedule( originRepoGroup );
-                originRepoGroup.close( );
-            }
-            RepositoryProvider provider = repositoryRegistry.getProvider( repositoryGroup.getType( ) );
-            RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration( repositoryGroup );
-            ReentrantReadWriteLock.WriteLock configLock = this.configurationHandler.getLock( ).writeLock( );
-            configLock.lock( );
-            try
-            {
-                Configuration configuration = this.configurationHandler.getBaseConfiguration( );
-                updateReferences( repositoryGroup, newCfg );
-                RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( id );
-                if ( oldCfg != null )
-                {
-                    configuration.removeRepositoryGroup( oldCfg );
-                }
-                configuration.addRepositoryGroup( newCfg );
-                configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
-                initializeGroup( repositoryGroup );
-            }
-            finally
-            {
-                configLock.unlock( );
-            }
-            repositoryGroups.put( id, repositoryGroup );
-            return repositoryGroup;
-        }
-        catch ( Exception e )
-        {
-            // Rollback
-            if ( originRepoGroup != null )
-            {
-                repositoryGroups.put( id, originRepoGroup );
-            }
-            else
-            {
-                repositoryGroups.remove( id );
-            }
-            log.error( "Exception during configuration update {}", e.getMessage( ), e );
-            throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ), e);
-        }
-    }
-
-    /**
-     * Adds a new repository group or updates the repository with the same id, if it exists already.
-     * The configuration is saved immediately.
-     *
-     * @param repositoryGroupConfiguration the repository configuration
-     * @return the updated or created repository
-     * @throws RepositoryException if an error occurs, or the configuration is not valid.
-     */
-    @Override
-    public RepositoryGroup put( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException
-    {
-        final String id = repositoryGroupConfiguration.getId( );
-        final RepositoryType repositoryType = RepositoryType.valueOf( repositoryGroupConfiguration.getType( ) );
-        final RepositoryProvider provider = repositoryRegistry.getProvider( repositoryType );
-        RepositoryGroup currentRepository;
-        ReentrantReadWriteLock.WriteLock configLock = this.configurationHandler.getLock( ).writeLock( );
-        configLock.lock( );
-        try
-        {
-            Configuration configuration = this.configurationHandler.getBaseConfiguration( );
-            currentRepository = repositoryRegistry.getRepositoryGroup( id );
-            RepositoryGroup oldRepository = currentRepository == null ? null : clone( currentRepository );
-            try
-            {
-
-                if (currentRepository==null) {
-                    currentRepository = put( repositoryGroupConfiguration, configuration );
-                } else
-                {
-                    setRepositoryGroupDefaults( repositoryGroupConfiguration );
-                    provider.updateRepositoryGroupInstance( (EditableRepositoryGroup) currentRepository, repositoryGroupConfiguration );
-                }
-                configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
-                updateReferences( currentRepository, repositoryGroupConfiguration );
-                initializeGroup( currentRepository );
-                this.repositoryGroups.put( id, currentRepository );
-            }
-            catch ( IndeterminateConfigurationException | RegistryException | RepositoryException e )
-            {
-                // Trying a rollback
-                if ( oldRepository != null  )
-                {
-                    RepositoryGroupConfiguration oldCfg = provider.getRepositoryGroupConfiguration( oldRepository );
-                    provider.updateRepositoryGroupInstance( (EditableRepositoryGroup) currentRepository, oldCfg);
-                    replaceOrAddRepositoryConfig( oldCfg, configuration );
-                    try
-                    {
-                        configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
-                    }
-                    catch ( IndeterminateConfigurationException | RegistryException indeterminateConfigurationException )
-                    {
-                        log.error( "Fatal error, config save during rollback failed: {}", e.getMessage( ), e );
-                    }
-                    updateReferences( oldRepository, oldCfg  );
-                    initializeGroup( oldRepository );
-                }
-                log.error( "Could not save the configuration for repository group {}: {}", id, e.getMessage( ), e );
-                if (e instanceof RepositoryException) {
-                    throw (RepositoryException) e;
-                } else
-                {
-                    throw new RepositoryException( "Could not save the configuration for repository group " + id + ": " + e.getMessage( ) );
-                }
-            }
-        }
-        finally
-        {
-            configLock.unlock( );
-        }
-        return currentRepository;
-    }
-
-    @Override
-    public RepositoryGroup put( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException
-    {
-        final String id = repositoryGroupConfiguration.getId( );
-        final RepositoryType repoType = RepositoryType.valueOf( repositoryGroupConfiguration.getType( ) );
-        RepositoryGroup repo;
-        setRepositoryGroupDefaults( repositoryGroupConfiguration );
-        if ( repositoryGroups.containsKey( id ) )
-        {
-            repo = clone( repositoryGroups.get( id ) );
-            if ( repo instanceof EditableRepositoryGroup )
-            {
-                repositoryRegistry.getProvider( repoType ).updateRepositoryGroupInstance( (EditableRepositoryGroup) repo, repositoryGroupConfiguration );
-            }
-            else
-            {
-                throw new RepositoryException( "The repository is not editable " + id );
-            }
-        }
-        else
-        {
-            repo = repositoryRegistry.getProvider( repoType ).createRepositoryGroup( repositoryGroupConfiguration );
-        }
-        replaceOrAddRepositoryConfig( repositoryGroupConfiguration, configuration );
-        updateReferences( repo, repositoryGroupConfiguration );
-        return repo;
-    }
-
-    @Override
-    public <D> CheckedResult<RepositoryGroup, D> putWithCheck( RepositoryGroupConfiguration repositoryConfiguration, RepositoryChecker<RepositoryGroup, D> checker ) throws RepositoryException
-    {
-        final String id = repositoryConfiguration.getId( );
-        RepositoryGroup currentGroup = repositoryGroups.get( id );
-        Configuration configuration = configurationHandler.getBaseConfiguration( );
-        RepositoryGroup repositoryGroup = put( repositoryConfiguration, configuration );
-        CheckedResult<RepositoryGroup, D> result;
-        if ( currentGroup == null )
-        {
-            result = checker.apply( repositoryGroup );
-        }
-        else
-        {
-            result = checker.applyForUpdate( repositoryGroup );
-        }
-        if ( result.isValid( ) )
-        {
-            put( result.getRepository() );
-        }
-        return result;
-    }
-
-
-    private void setRepositoryGroupDefaults( RepositoryGroupConfiguration repositoryGroupConfiguration )
-    {
-        if ( StringUtils.isEmpty( repositoryGroupConfiguration.getMergedIndexPath( ) ) )
-        {
-            repositoryGroupConfiguration.setMergedIndexPath( DEFAULT_INDEX_PATH );
-        }
-        if ( repositoryGroupConfiguration.getMergedIndexTtl( ) <= 0 )
-        {
-            repositoryGroupConfiguration.setMergedIndexTtl( 300 );
-        }
-        if ( StringUtils.isEmpty( repositoryGroupConfiguration.getCronExpression( ) ) )
-        {
-            repositoryGroupConfiguration.setCronExpression( "0 0 03 ? * MON" );
-        }
-    }
-
-    private void replaceOrAddRepositoryConfig( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration )
-    {
-        RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( repositoryGroupConfiguration.getId( ) );
-        if ( oldCfg != null )
-        {
-            configuration.removeRepositoryGroup( oldCfg );
-        }
-        configuration.addRepositoryGroup( repositoryGroupConfiguration );
-    }
-
-    public void removeRepositoryFromGroups( ManagedRepository repo )
-    {
-        if ( repo != null )
-        {
-            repositoryGroups.values( ).stream( ).filter( repoGroup -> repoGroup instanceof EditableRepository ).
-                map( repoGroup -> (EditableRepositoryGroup) repoGroup ).forEach( repoGroup -> repoGroup.removeRepository( repo ) );
-        }
-    }
-
-    /**
-     * Removes a repository group from the registry and configuration, if it exists.
-     * The change is saved to the configuration immediately.
-     *
-     * @param id the id of the repository group to remove
-     * @throws RepositoryException if a error occurs during configuration save
-     */
-    @Override
-    public void remove( final String id ) throws RepositoryException
-    {
-        RepositoryGroup repo = get( id );
-        if ( repo != null )
-        {
-            try
-            {
-                repo = repositoryGroups.remove( id );
-                if ( repo != null )
-                {
-                    this.mergedRemoteIndexesScheduler.unschedule( repo );
-                    repo.close( );
-                    Configuration configuration = this.configurationHandler.getBaseConfiguration( );
-                    RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
-                    if ( cfg != null )
-                    {
-                        configuration.removeRepositoryGroup( cfg );
-                    }
-                    this.configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
-                }
-
-            }
-            catch ( RegistryException | IndeterminateConfigurationException e )
-            {
-                // Rollback
-                log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
-                repositoryGroups.put( repo.getId( ), repo );
-                throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
-            }
-        }
-    }
-
-    @Override
-    public void remove( String id, Configuration configuration ) throws RepositoryException
-    {
-        RepositoryGroup repo = repositoryGroups.get( id );
-        if ( repo != null )
-        {
-            repo = repositoryGroups.remove( id );
-            if ( repo != null )
-            {
-                this.mergedRemoteIndexesScheduler.unschedule( repo );
-                repo.close( );
-                RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
-                if ( cfg != null )
-                {
-                    configuration.removeRepositoryGroup( cfg );
-                }
-            }
-        }
-
-    }
-
-    @Override
-    public RepositoryGroup get( String groupId )
-    {
-        return repositoryGroups.get( groupId );
-    }
-
-    @Override
-    public RepositoryGroup clone( RepositoryGroup repo ) throws RepositoryException
-    {
-        RepositoryProvider provider = repositoryRegistry.getProvider( repo.getType( ) );
-        RepositoryGroupConfiguration cfg = provider.getRepositoryGroupConfiguration( repo );
-        RepositoryGroup cloned = provider.createRepositoryGroup( cfg );
-        cloned.registerEventHandler( RepositoryEvent.ANY, repositoryRegistry );
-        return cloned;
-    }
-
-    @Override
-    public void updateReferences( RepositoryGroup repo, RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException
-    {
-        if ( repo instanceof EditableRepositoryGroup )
-        {
-            EditableRepositoryGroup eGroup = (EditableRepositoryGroup) repo;
-            eGroup.setRepositories( repositoryConfiguration.getRepositories( ).stream( )
-                .map( repositoryRegistry::getManagedRepository ).collect( Collectors.toList( ) ) );
-        }
-
-    }
-
-    @Override
-    public Collection<RepositoryGroup> getAll( )
-    {
-        return repositoryGroups.values( );
-    }
-
-    @Override
-    public RepositoryValidator<RepositoryGroup> getValidator( )
-    {
-        return this.validator;
-    }
-
-    @Override
-    public boolean has( String id )
-    {
-        return repositoryGroups.containsKey( id );
-    }
-
-    @PreDestroy
-    private void destroy( )
-    {
-        this.close( );
-    }
-
-    @Override
-    public void close( )
-    {
-        for ( RepositoryGroup group : repositoryGroups.values( ) )
-        {
-            try
-            {
-                mergedRemoteIndexesScheduler.unschedule( group );
-                group.close( );
-            }
-            catch ( Throwable e )
-            {
-                log.error( "Could not close repository group {}: {}", group.getId( ), e.getMessage( ) );
-            }
-        }
-        this.repositoryGroups.clear( );
-    }
-
-}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/AbstractRepositoryGroup.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/AbstractRepositoryGroup.java
new file mode 100644 (file)
index 0000000..d24f00e
--- /dev/null
@@ -0,0 +1,177 @@
+package org.apache.archiva.repository.base.group;
+
+/*
+ * 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.EditableRepositoryGroup;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.RepositoryCapabilities;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.base.AbstractRepository;
+import org.apache.archiva.repository.storage.RepositoryStorage;
+import org.apache.commons.collections4.map.ListOrderedMap;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * Abstract repository group implementation.
+ *
+ */
+public class AbstractRepositoryGroup extends AbstractRepository implements EditableRepositoryGroup
+{
+
+    private final ListOrderedMap<String, ManagedRepository> repositories = new ListOrderedMap<>();
+
+    private int mergedIndexTTL;
+
+    private final ReadWriteLock rwl = new ReentrantReadWriteLock();
+
+    private RepositoryCapabilities capabilities;
+
+    public AbstractRepositoryGroup( RepositoryType type, String id, String name, RepositoryStorage storage) {
+        super(type, id, name, storage);
+    }
+
+    public AbstractRepositoryGroup(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage) {
+        super(primaryLocale, type, id, name, storage);
+    }
+
+    @Override
+    public boolean hasIndex() {
+        return true;
+    }
+
+    @Override
+    public RepositoryCapabilities getCapabilities() {
+        return capabilities;
+    }
+
+
+    @Override
+    public void clearRepositories() {
+        rwl.writeLock().lock();
+        try {
+            repositories.clear();
+        } finally {
+            rwl.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public void setRepositories(List<ManagedRepository> newRepositories) {
+        rwl.writeLock().lock();
+        try {
+            repositories.clear();
+            for(ManagedRepository repo : newRepositories) {
+                if (repo!=null)
+                    repositories.put(repo.getId(), repo);
+            }
+        } finally {
+            rwl.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public void addRepository(ManagedRepository repository) {
+        rwl.writeLock().lock();
+        try {
+            if (repository!=null)
+                repositories.put(repository.getId(), repository);
+        } finally {
+            rwl.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public void addRepository(int index, ManagedRepository repository) {
+        rwl.writeLock().lock();
+        try {
+            if (repository!=null)
+                repositories.put(index, repository.getId(), repository);
+        } finally {
+            rwl.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public boolean removeRepository(ManagedRepository repository) {
+        rwl.writeLock().lock();
+        try {
+            return repositories.remove(repository.getId(), repository);
+        } finally {
+            rwl.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public ManagedRepository removeRepository(String repoId) {
+        rwl.writeLock().lock();
+        try {
+            return repositories.remove(repoId);
+        } finally {
+            rwl.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public void setMergedIndexTTL(int timeInSeconds) {
+        this.mergedIndexTTL = timeInSeconds;
+    }
+
+    @Override
+    public List<ManagedRepository> getRepositories() {
+        rwl.readLock().lock();
+        try {
+            return repositories.valueList();
+        } finally {
+            rwl.readLock().unlock();
+        }
+    }
+
+    @Override
+    public boolean contains(ManagedRepository repository) {
+        rwl.readLock().lock();
+        try {
+            return repositories.containsValue(repository);
+        } finally {
+            rwl.readLock().unlock();
+        }
+    }
+
+    @Override
+    public boolean contains(String id) {
+        rwl.readLock().lock();
+        try {
+            return repositories.containsKey(id);
+        } finally {
+            rwl.readLock().unlock();
+        }
+    }
+
+    @Override
+    public int getMergedIndexTTL() {
+        return mergedIndexTTL;
+    }
+
+    protected void setCapabilities(RepositoryCapabilities capabilities) {
+        this.capabilities = capabilities;
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/BasicRepositoryGroupValidator.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/BasicRepositoryGroupValidator.java
new file mode 100644 (file)
index 0000000..308dd3a
--- /dev/null
@@ -0,0 +1,131 @@
+package org.apache.archiva.repository.base.group;
+/*
+ * 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.RepositoryGroup;
+import org.apache.archiva.repository.RepositoryRegistry;
+import org.apache.archiva.repository.base.ConfigurationHandler;
+import org.apache.archiva.repository.validation.AbstractRepositoryValidator;
+import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationError;
+import org.apache.archiva.repository.validation.ValidationResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.apache.archiva.repository.validation.ErrorKeys.*;
+
+/**
+ *
+ * A validator for repository groups. All validation errors are prefixed with category 'repository_group'.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Service( "repositoryValidator#common#group" )
+public class BasicRepositoryGroupValidator extends AbstractRepositoryValidator<RepositoryGroup> implements RepositoryValidator<RepositoryGroup>
+{
+
+    private static final String CATEGORY = "repository_group";
+    private static final Pattern REPO_GROUP_ID_PATTERN = Pattern.compile( "[A-Za-z0-9._\\-]+" );
+    private final ConfigurationHandler configurationHandler;
+
+    private RepositoryRegistry repositoryRegistry;
+
+    public BasicRepositoryGroupValidator( ConfigurationHandler configurationHandler )
+    {
+        super( CATEGORY );
+        this.configurationHandler = configurationHandler;
+    }
+
+
+    @Override
+    public ValidationResponse<RepositoryGroup> apply( RepositoryGroup repositoryGroup, boolean updateMode ) throws IllegalArgumentException
+    {
+        final String repoGroupId = repositoryGroup.getId( );
+        Map<String, List<ValidationError>> errors = null;
+        if ( StringUtils.isBlank( repoGroupId ) )
+        {
+            errors = appendError( null, "id", ISEMPTY );
+        }
+
+        if ( repoGroupId.length( ) > 100 )
+        {
+            errors = appendError( errors, "id", MAX_LENGTH_EXCEEDED, repoGroupId, Integer.toString( 100 ) );
+
+        }
+
+        Matcher matcher = REPO_GROUP_ID_PATTERN.matcher( repoGroupId );
+        if ( !matcher.matches( ) )
+        {
+            errors = appendError( errors, "id", INVALID_CHARS, repoGroupId, new String[]{"alphanumeric, '.', '-','_'"} );
+        }
+
+        if ( repositoryGroup.getMergedIndexTTL( ) <= 0 )
+        {
+            errors = appendError( errors, "merged_index_ttl",BELOW_MIN, "0" );
+        }
+
+
+        if ( repositoryRegistry != null && !updateMode )
+        {
+            if ( repositoryRegistry.hasRepositoryGroup( repoGroupId ) )
+            {
+                errors = appendError( errors, "id", REPOSITORY_GROUP_EXISTS, repoGroupId );
+            }
+            else if ( repositoryRegistry.hasManagedRepository( repoGroupId ) )
+            {
+                errors = appendError( errors, "id", MANAGED_REPOSITORY_EXISTS );
+            }
+            else if ( repositoryRegistry.hasRemoteRepository( repoGroupId ) )
+            {
+                errors = appendError( errors, "id", REMOTE_REPOSITORY_EXISTS );
+            }
+        }
+        return new ValidationResponse<>(repositoryGroup, errors );
+    }
+
+
+
+
+    public ConfigurationHandler getConfigurationHandler( )
+    {
+        return configurationHandler;
+    }
+
+    public RepositoryRegistry getRepositoryRegistry( )
+    {
+        return repositoryRegistry;
+    }
+
+    @Override
+    public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
+    {
+        this.repositoryRegistry = repositoryRegistry;
+    }
+
+    @Override
+    public Class<RepositoryGroup> getFlavour( )
+    {
+        return RepositoryGroup.class;
+    }
+
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/RepositoryGroupHandler.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/RepositoryGroupHandler.java
new file mode 100644 (file)
index 0000000..dba60f8
--- /dev/null
@@ -0,0 +1,625 @@
+package org.apache.archiva.repository.base.group;
+/*
+ * 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.registry.RegistryException;
+import org.apache.archiva.configuration.Configuration;
+import org.apache.archiva.configuration.IndeterminateConfigurationException;
+import org.apache.archiva.configuration.RepositoryGroupConfiguration;
+import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler;
+import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
+import org.apache.archiva.repository.base.ConfigurationHandler;
+import org.apache.archiva.repository.validation.CheckedResult;
+import org.apache.archiva.repository.EditableRepository;
+import org.apache.archiva.repository.EditableRepositoryGroup;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryException;
+import org.apache.archiva.repository.RepositoryGroup;
+import org.apache.archiva.repository.RepositoryHandler;
+import org.apache.archiva.repository.RepositoryProvider;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.event.RepositoryEvent;
+import org.apache.archiva.repository.features.IndexCreationFeature;
+import org.apache.archiva.repository.storage.StorageAsset;
+import org.apache.archiva.repository.validation.CombinedValidator;
+import org.apache.archiva.repository.validation.RepositoryChecker;
+import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Named;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.stream.Collectors;
+
+import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
+
+/**
+ * This class manages repository groups for the RepositoryRegistry.
+ * It is tightly coupled with the {@link ArchivaRepositoryRegistry}.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Service( "repositoryGroupHandler#default" )
+public class RepositoryGroupHandler implements RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration>
+{
+    private static final Logger log = LoggerFactory.getLogger( RepositoryGroupHandler.class );
+
+    private final ArchivaRepositoryRegistry repositoryRegistry;
+    private final ConfigurationHandler configurationHandler;
+    private final MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
+
+    private final Map<String, RepositoryGroup> repositoryGroups = new HashMap<>( );
+    private final RepositoryValidator<RepositoryGroup> validator;
+
+    private Path groupsDirectory;
+
+
+    /**
+     * Creates a new instance. All dependencies are injected on the constructor.
+     *
+     * @param repositoryRegistry           the registry. To avoid circular dependencies via DI, this class registers itself on the registry.
+     * @param configurationHandler         the configuration handler is used to retrieve and save configuration.
+     * @param mergedRemoteIndexesScheduler the index scheduler is used for merging the indexes from all group members
+     */
+    public RepositoryGroupHandler( ArchivaRepositoryRegistry repositoryRegistry,
+                                   ConfigurationHandler configurationHandler,
+                                   @Named( "mergedRemoteIndexesScheduler#default" ) MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler,
+                                   List<RepositoryValidator<? extends Repository>> repositoryGroupValidatorList
+                                   )
+    {
+        this.configurationHandler = configurationHandler;
+        this.mergedRemoteIndexesScheduler = mergedRemoteIndexesScheduler;
+        this.repositoryRegistry = repositoryRegistry;
+        List<RepositoryValidator<RepositoryGroup>> validatorList = initValidators( repositoryGroupValidatorList );
+        this.validator = new CombinedValidator<>( RepositoryGroup.class, validatorList );
+    }
+
+    private List<RepositoryValidator<RepositoryGroup>> initValidators(List<RepositoryValidator<? extends Repository>> repositoryGroupValidatorList) {
+        if (repositoryGroupValidatorList!=null && repositoryGroupValidatorList.size()>0) {
+            return repositoryGroupValidatorList.stream( ).filter(
+                v -> v.isFlavour( RepositoryGroup.class )
+            ).map( v -> v.narrowTo( RepositoryGroup.class ) ).collect( Collectors.toList( ) );
+        } else {
+            return Collections.emptyList( );
+        }
+    }
+
+    @Override
+    @PostConstruct
+    public void init( )
+    {
+        log.debug( "Initializing repository group handler " + repositoryRegistry.toString( ) );
+        initializeStorage( );
+        // We are registering this class on the registry. This is necessary to avoid circular dependencies via injection.
+        this.repositoryRegistry.registerGroupHandler( this );
+    }
+
+    public void initializeFromConfig( )
+    {
+        this.repositoryGroups.clear( );
+        this.repositoryGroups.putAll( newInstancesFromConfig( ) );
+        for ( RepositoryGroup group : this.repositoryGroups.values( ) )
+        {
+            initializeGroup( group );
+        }
+    }
+
+    private void initializeStorage( )
+    {
+        Path baseDir = this.configurationHandler.getArchivaConfiguration( ).getRepositoryGroupBaseDir( );
+        if ( !Files.exists( baseDir ) )
+        {
+            try
+            {
+                Files.createDirectories( baseDir );
+            }
+            catch ( IOException e )
+            {
+                log.error( "Could not create group base directory: {}", e.getMessage( ), e );
+            }
+        }
+        this.groupsDirectory = baseDir;
+    }
+
+    private void initializeGroup( RepositoryGroup repositoryGroup )
+    {
+        StorageAsset indexDirectory = getMergedIndexDirectory( repositoryGroup );
+        if ( !indexDirectory.exists( ) )
+        {
+            try
+            {
+                indexDirectory.create( );
+            }
+            catch ( IOException e )
+            {
+                log.error( "Could not create index directory {} for group {}: {}", indexDirectory, repositoryGroup.getId( ), e.getMessage( ) );
+            }
+        }
+        Path groupPath = groupsDirectory.resolve( repositoryGroup.getId( ) );
+        if ( !Files.exists( groupPath ) )
+        {
+            try
+            {
+                Files.createDirectories( groupPath );
+            }
+            catch ( IOException e )
+            {
+                log.error( "Could not create repository group directory {}", groupPath );
+            }
+        }
+        mergedRemoteIndexesScheduler.schedule( repositoryGroup,
+            indexDirectory );
+    }
+
+    public StorageAsset getMergedIndexDirectory( RepositoryGroup group )
+    {
+        if ( group != null )
+        {
+            return group.getFeature( IndexCreationFeature.class ).get( ).getLocalIndexPath( );
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    @Override
+    public Map<String, RepositoryGroup> newInstancesFromConfig( )
+    {
+        try
+        {
+            List<RepositoryGroupConfiguration> repositoryGroupConfigurations =
+                this.configurationHandler.getBaseConfiguration( ).getRepositoryGroups( );
+
+            if ( repositoryGroupConfigurations == null )
+            {
+                return Collections.emptyMap( );
+            }
+
+            Map<String, RepositoryGroup> repositoryGroupMap = new LinkedHashMap<>( repositoryGroupConfigurations.size( ) );
+
+            Map<RepositoryType, RepositoryProvider> providerMap = repositoryRegistry.getRepositoryProviderMap( );
+            for ( RepositoryGroupConfiguration repoConfig : repositoryGroupConfigurations )
+            {
+                RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
+                if ( providerMap.containsKey( repositoryType ) )
+                {
+                    try
+                    {
+                        RepositoryGroup repo = createNewRepositoryGroup( providerMap.get( repositoryType ), repoConfig );
+                        repositoryGroupMap.put( repo.getId( ), repo );
+                    }
+                    catch ( Exception e )
+                    {
+                        log.error( "Could not create repository group {}: {}", repoConfig.getId( ), e.getMessage( ), e );
+                    }
+                }
+            }
+            return repositoryGroupMap;
+        }
+        catch ( Throwable e )
+        {
+            log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
+            return Collections.emptyMap( );
+        }
+    }
+
+    @Override
+    public RepositoryGroup newInstance( final RepositoryType type, String id ) throws RepositoryException
+    {
+        RepositoryProvider provider = repositoryRegistry.getProvider( type );
+        RepositoryGroupConfiguration config = new RepositoryGroupConfiguration( );
+        config.setId( id );
+        return createNewRepositoryGroup( provider, config );
+    }
+
+    @Override
+    public RepositoryGroup newInstance( final RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException
+    {
+        RepositoryType type = RepositoryType.valueOf( repositoryConfiguration.getType( ) );
+        RepositoryProvider provider = repositoryRegistry.getProvider( type );
+        return createNewRepositoryGroup( provider, repositoryConfiguration );
+    }
+
+    private RepositoryGroup createNewRepositoryGroup( RepositoryProvider provider, RepositoryGroupConfiguration config ) throws RepositoryException
+    {
+        RepositoryGroup repositoryGroup = provider.createRepositoryGroup( config );
+        updateReferences( repositoryGroup, config );
+        return repositoryGroup;
+    }
+
+
+    /**
+     * Adds a new repository group to the current list, or replaces the repository group definition with
+     * the same id, if it exists already.
+     * The change is saved to the configuration immediately.
+     *
+     * @param repositoryGroup the new repository group.
+     * @throws RepositoryException if the new repository group could not be saved to the configuration.
+     */
+    @Override
+    public RepositoryGroup put( final RepositoryGroup repositoryGroup ) throws RepositoryException
+    {
+        final String id = repositoryGroup.getId( );
+        RepositoryGroup originRepoGroup = repositoryGroups.remove( id );
+        try
+        {
+            if ( originRepoGroup != null && originRepoGroup != repositoryGroup )
+            {
+                this.mergedRemoteIndexesScheduler.unschedule( originRepoGroup );
+                originRepoGroup.close( );
+            }
+            RepositoryProvider provider = repositoryRegistry.getProvider( repositoryGroup.getType( ) );
+            RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration( repositoryGroup );
+            ReentrantReadWriteLock.WriteLock configLock = this.configurationHandler.getLock( ).writeLock( );
+            configLock.lock( );
+            try
+            {
+                Configuration configuration = this.configurationHandler.getBaseConfiguration( );
+                updateReferences( repositoryGroup, newCfg );
+                RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( id );
+                if ( oldCfg != null )
+                {
+                    configuration.removeRepositoryGroup( oldCfg );
+                }
+                configuration.addRepositoryGroup( newCfg );
+                configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
+                initializeGroup( repositoryGroup );
+            }
+            finally
+            {
+                configLock.unlock( );
+            }
+            repositoryGroups.put( id, repositoryGroup );
+            return repositoryGroup;
+        }
+        catch ( Exception e )
+        {
+            // Rollback
+            if ( originRepoGroup != null )
+            {
+                repositoryGroups.put( id, originRepoGroup );
+            }
+            else
+            {
+                repositoryGroups.remove( id );
+            }
+            log.error( "Exception during configuration update {}", e.getMessage( ), e );
+            throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ), e);
+        }
+    }
+
+    /**
+     * Adds a new repository group or updates the repository with the same id, if it exists already.
+     * The configuration is saved immediately.
+     *
+     * @param repositoryGroupConfiguration the repository configuration
+     * @return the updated or created repository
+     * @throws RepositoryException if an error occurs, or the configuration is not valid.
+     */
+    @Override
+    public RepositoryGroup put( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException
+    {
+        final String id = repositoryGroupConfiguration.getId( );
+        final RepositoryType repositoryType = RepositoryType.valueOf( repositoryGroupConfiguration.getType( ) );
+        final RepositoryProvider provider = repositoryRegistry.getProvider( repositoryType );
+        RepositoryGroup currentRepository;
+        ReentrantReadWriteLock.WriteLock configLock = this.configurationHandler.getLock( ).writeLock( );
+        configLock.lock( );
+        try
+        {
+            Configuration configuration = this.configurationHandler.getBaseConfiguration( );
+            currentRepository = repositoryRegistry.getRepositoryGroup( id );
+            RepositoryGroup oldRepository = currentRepository == null ? null : clone( currentRepository );
+            try
+            {
+
+                if (currentRepository==null) {
+                    currentRepository = put( repositoryGroupConfiguration, configuration );
+                } else
+                {
+                    setRepositoryGroupDefaults( repositoryGroupConfiguration );
+                    provider.updateRepositoryGroupInstance( (EditableRepositoryGroup) currentRepository, repositoryGroupConfiguration );
+                }
+                configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
+                updateReferences( currentRepository, repositoryGroupConfiguration );
+                initializeGroup( currentRepository );
+                this.repositoryGroups.put( id, currentRepository );
+            }
+            catch ( IndeterminateConfigurationException | RegistryException | RepositoryException e )
+            {
+                // Trying a rollback
+                if ( oldRepository != null  )
+                {
+                    RepositoryGroupConfiguration oldCfg = provider.getRepositoryGroupConfiguration( oldRepository );
+                    provider.updateRepositoryGroupInstance( (EditableRepositoryGroup) currentRepository, oldCfg);
+                    replaceOrAddRepositoryConfig( oldCfg, configuration );
+                    try
+                    {
+                        configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
+                    }
+                    catch ( IndeterminateConfigurationException | RegistryException indeterminateConfigurationException )
+                    {
+                        log.error( "Fatal error, config save during rollback failed: {}", e.getMessage( ), e );
+                    }
+                    updateReferences( oldRepository, oldCfg  );
+                    initializeGroup( oldRepository );
+                }
+                log.error( "Could not save the configuration for repository group {}: {}", id, e.getMessage( ), e );
+                if (e instanceof RepositoryException) {
+                    throw (RepositoryException) e;
+                } else
+                {
+                    throw new RepositoryException( "Could not save the configuration for repository group " + id + ": " + e.getMessage( ) );
+                }
+            }
+        }
+        finally
+        {
+            configLock.unlock( );
+        }
+        return currentRepository;
+    }
+
+    @Override
+    public RepositoryGroup put( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException
+    {
+        final String id = repositoryGroupConfiguration.getId( );
+        final RepositoryType repoType = RepositoryType.valueOf( repositoryGroupConfiguration.getType( ) );
+        RepositoryGroup repo;
+        setRepositoryGroupDefaults( repositoryGroupConfiguration );
+        if ( repositoryGroups.containsKey( id ) )
+        {
+            repo = clone( repositoryGroups.get( id ) );
+            if ( repo instanceof EditableRepositoryGroup )
+            {
+                repositoryRegistry.getProvider( repoType ).updateRepositoryGroupInstance( (EditableRepositoryGroup) repo, repositoryGroupConfiguration );
+            }
+            else
+            {
+                throw new RepositoryException( "The repository is not editable " + id );
+            }
+        }
+        else
+        {
+            repo = repositoryRegistry.getProvider( repoType ).createRepositoryGroup( repositoryGroupConfiguration );
+        }
+        replaceOrAddRepositoryConfig( repositoryGroupConfiguration, configuration );
+        updateReferences( repo, repositoryGroupConfiguration );
+        return repo;
+    }
+
+    @Override
+    public <D> CheckedResult<RepositoryGroup, D> putWithCheck( RepositoryGroupConfiguration repositoryConfiguration, RepositoryChecker<RepositoryGroup, D> checker ) throws RepositoryException
+    {
+        final String id = repositoryConfiguration.getId( );
+        RepositoryGroup currentGroup = repositoryGroups.get( id );
+        Configuration configuration = configurationHandler.getBaseConfiguration( );
+        RepositoryGroup repositoryGroup = put( repositoryConfiguration, configuration );
+        CheckedResult<RepositoryGroup, D> result;
+        if ( currentGroup == null )
+        {
+            result = checker.apply( repositoryGroup );
+        }
+        else
+        {
+            result = checker.applyForUpdate( repositoryGroup );
+        }
+        if ( result.isValid( ) )
+        {
+            put( result.getRepository() );
+        }
+        return result;
+    }
+
+
+    private void setRepositoryGroupDefaults( RepositoryGroupConfiguration repositoryGroupConfiguration )
+    {
+        if ( StringUtils.isEmpty( repositoryGroupConfiguration.getMergedIndexPath( ) ) )
+        {
+            repositoryGroupConfiguration.setMergedIndexPath( DEFAULT_INDEX_PATH );
+        }
+        if ( repositoryGroupConfiguration.getMergedIndexTtl( ) <= 0 )
+        {
+            repositoryGroupConfiguration.setMergedIndexTtl( 300 );
+        }
+        if ( StringUtils.isEmpty( repositoryGroupConfiguration.getCronExpression( ) ) )
+        {
+            repositoryGroupConfiguration.setCronExpression( "0 0 03 ? * MON" );
+        }
+    }
+
+    private void replaceOrAddRepositoryConfig( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration )
+    {
+        RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( repositoryGroupConfiguration.getId( ) );
+        if ( oldCfg != null )
+        {
+            configuration.removeRepositoryGroup( oldCfg );
+        }
+        configuration.addRepositoryGroup( repositoryGroupConfiguration );
+    }
+
+    public void removeRepositoryFromGroups( ManagedRepository repo )
+    {
+        if ( repo != null )
+        {
+            repositoryGroups.values( ).stream( ).filter( repoGroup -> repoGroup instanceof EditableRepository ).
+                map( repoGroup -> (EditableRepositoryGroup) repoGroup ).forEach( repoGroup -> repoGroup.removeRepository( repo ) );
+        }
+    }
+
+    /**
+     * Removes a repository group from the registry and configuration, if it exists.
+     * The change is saved to the configuration immediately.
+     *
+     * @param id the id of the repository group to remove
+     * @throws RepositoryException if a error occurs during configuration save
+     */
+    @Override
+    public void remove( final String id ) throws RepositoryException
+    {
+        RepositoryGroup repo = get( id );
+        if ( repo != null )
+        {
+            try
+            {
+                repo = repositoryGroups.remove( id );
+                if ( repo != null )
+                {
+                    this.mergedRemoteIndexesScheduler.unschedule( repo );
+                    repo.close( );
+                    Configuration configuration = this.configurationHandler.getBaseConfiguration( );
+                    RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
+                    if ( cfg != null )
+                    {
+                        configuration.removeRepositoryGroup( cfg );
+                    }
+                    this.configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
+                }
+
+            }
+            catch ( RegistryException | IndeterminateConfigurationException e )
+            {
+                // Rollback
+                log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
+                repositoryGroups.put( repo.getId( ), repo );
+                throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
+            }
+        }
+    }
+
+    @Override
+    public void remove( String id, Configuration configuration ) throws RepositoryException
+    {
+        RepositoryGroup repo = repositoryGroups.get( id );
+        if ( repo != null )
+        {
+            repo = repositoryGroups.remove( id );
+            if ( repo != null )
+            {
+                this.mergedRemoteIndexesScheduler.unschedule( repo );
+                repo.close( );
+                RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
+                if ( cfg != null )
+                {
+                    configuration.removeRepositoryGroup( cfg );
+                }
+            }
+        }
+
+    }
+
+    @Override
+    public RepositoryGroup get( String groupId )
+    {
+        return repositoryGroups.get( groupId );
+    }
+
+    @Override
+    public RepositoryGroup clone( RepositoryGroup repo ) throws RepositoryException
+    {
+        RepositoryProvider provider = repositoryRegistry.getProvider( repo.getType( ) );
+        RepositoryGroupConfiguration cfg = provider.getRepositoryGroupConfiguration( repo );
+        RepositoryGroup cloned = provider.createRepositoryGroup( cfg );
+        cloned.registerEventHandler( RepositoryEvent.ANY, repositoryRegistry );
+        return cloned;
+    }
+
+    @Override
+    public void updateReferences( RepositoryGroup repo, RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException
+    {
+        if ( repo instanceof EditableRepositoryGroup )
+        {
+            EditableRepositoryGroup eGroup = (EditableRepositoryGroup) repo;
+            eGroup.setRepositories( repositoryConfiguration.getRepositories( ).stream( )
+                .map( repositoryRegistry::getManagedRepository ).collect( Collectors.toList( ) ) );
+        }
+
+    }
+
+    @Override
+    public Collection<RepositoryGroup> getAll( )
+    {
+        return repositoryGroups.values( );
+    }
+
+    @Override
+    public RepositoryValidator<RepositoryGroup> getValidator( )
+    {
+        return this.validator;
+    }
+
+    @Override
+    public ValidationResponse<RepositoryGroup> validateRepository( RepositoryGroup repository )
+    {
+        return null;
+    }
+
+    @Override
+    public ValidationResponse<RepositoryGroup> validateRepositoryForUpdate( RepositoryGroup repository )
+    {
+        return null;
+    }
+
+    @Override
+    public boolean has( String id )
+    {
+        return repositoryGroups.containsKey( id );
+    }
+
+    @PreDestroy
+    private void destroy( )
+    {
+        this.close( );
+    }
+
+    @Override
+    public void close( )
+    {
+        for ( RepositoryGroup group : repositoryGroups.values( ) )
+        {
+            try
+            {
+                mergedRemoteIndexesScheduler.unschedule( group );
+                group.close( );
+            }
+            catch ( Throwable e )
+            {
+                log.error( "Could not close repository group {}: {}", group.getId( ), e.getMessage( ) );
+            }
+        }
+        this.repositoryGroups.clear( );
+    }
+
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/AbstractManagedRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/AbstractManagedRepository.java
new file mode 100644 (file)
index 0000000..aaac150
--- /dev/null
@@ -0,0 +1,102 @@
+package org.apache.archiva.repository.base.managed;
+
+/*
+ * 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.EditableManagedRepository;
+import org.apache.archiva.repository.ManagedRepositoryContent;
+import org.apache.archiva.repository.ReleaseScheme;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.base.AbstractRepository;
+import org.apache.archiva.repository.storage.RepositoryStorage;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * Simple implementation of a managed repository.
+ */
+public abstract class AbstractManagedRepository extends AbstractRepository implements EditableManagedRepository
+{
+    private boolean blocksRedeployment = false;
+    private ManagedRepositoryContent content;
+    private Set<ReleaseScheme> activeReleaseSchemes = new HashSet<>(  );
+    private Set<ReleaseScheme> uActiveReleaseSchemes = Collections.unmodifiableSet( activeReleaseSchemes );
+
+    public AbstractManagedRepository( RepositoryType type, String id, String name, RepositoryStorage storage)
+    {
+        super( type, id, name, storage );
+    }
+
+    public AbstractManagedRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
+    {
+        super( primaryLocale, type, id, name, storage );
+    }
+
+    @Override
+    public ManagedRepositoryContent getContent( )
+    {
+        return content;
+    }
+
+    @Override
+    public void setContent( ManagedRepositoryContent content) {
+        this.content = content;
+    }
+
+    @Override
+    public void setBlocksRedeployment( boolean blocksRedeployment )
+    {
+        this.blocksRedeployment = blocksRedeployment;
+    }
+
+    @Override
+    public boolean blocksRedeployments( )
+    {
+        return blocksRedeployment;
+    }
+
+    @Override
+    public Set<ReleaseScheme> getActiveReleaseSchemes( )
+    {
+        return uActiveReleaseSchemes;
+    }
+
+    @Override
+    public void addActiveReleaseScheme( ReleaseScheme scheme )
+    {
+        this.activeReleaseSchemes.add(scheme);
+    }
+
+    @Override
+    public void removeActiveReleaseScheme( ReleaseScheme scheme )
+    {
+        this.activeReleaseSchemes.remove(scheme);
+    }
+
+    @Override
+    public void clearActiveReleaseSchemes( )
+    {
+        this.activeReleaseSchemes.clear();
+    }
+
+
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/BasicManagedRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/BasicManagedRepository.java
new file mode 100644 (file)
index 0000000..5840d22
--- /dev/null
@@ -0,0 +1,112 @@
+package org.apache.archiva.repository.base.managed;
+
+/*
+ * 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.common.filelock.DefaultFileLockManager;
+import org.apache.archiva.common.filelock.FileLockManager;
+import org.apache.archiva.repository.ReleaseScheme;
+import org.apache.archiva.repository.RepositoryCapabilities;
+import org.apache.archiva.repository.RepositoryRequestInfo;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.StandardCapabilities;
+import org.apache.archiva.repository.storage.fs.FilesystemStorage;
+import org.apache.archiva.repository.storage.RepositoryStorage;
+import org.apache.archiva.repository.features.ArtifactCleanupFeature;
+import org.apache.archiva.repository.features.IndexCreationFeature;
+import org.apache.archiva.repository.features.StagingRepositoryFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Locale;
+
+/**
+ *
+ * Just a helper class, mainly used for unit tests.
+ *
+ *
+ */
+public class BasicManagedRepository extends AbstractManagedRepository
+
+{
+    Logger log = LoggerFactory.getLogger(BasicManagedRepository.class);
+    ArtifactCleanupFeature artifactCleanupFeature = new ArtifactCleanupFeature(  );
+    StagingRepositoryFeature stagingRepositoryFeature = new StagingRepositoryFeature( );
+
+    static final StandardCapabilities CAPABILITIES = new StandardCapabilities( new ReleaseScheme[] {
+        ReleaseScheme.RELEASE, ReleaseScheme.SNAPSHOT
+    }, new String[] {"default"}, new String[0], new String[] {
+        ArtifactCleanupFeature.class.toString(), IndexCreationFeature.class.toString(),
+        StagingRepositoryFeature.class.toString()
+    }, true, true, true, true, true  );
+
+    public BasicManagedRepository( String id, String name, RepositoryStorage repositoryStorage )
+    {
+        super( RepositoryType.MAVEN, id, name, repositoryStorage );
+        initFeatures();
+    }
+
+    public BasicManagedRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage )
+    {
+        super( primaryLocale, type, id, name, repositoryStorage);
+        initFeatures();
+    }
+
+    private void initFeatures() {
+        IndexCreationFeature indexCreationFeature = new IndexCreationFeature(this, this);
+        addFeature( artifactCleanupFeature );
+        addFeature( indexCreationFeature );
+        addFeature( stagingRepositoryFeature );
+    }
+
+    @Override
+    public boolean hasIndex( )
+    {
+        return true;
+    }
+
+    @Override
+    public RepositoryCapabilities getCapabilities( )
+    {
+        return CAPABILITIES;
+    }
+
+
+    @Override
+    public RepositoryRequestInfo getRequestInfo() {
+        return null;
+    }
+
+    /**
+     * Creates a filesystem based repository instance. The path is built by basePath/repository-id
+     *
+     * @param id The repository id
+     * @param name The name of the repository
+     * @param repositoryPath The path to the repository
+     * @return The repository instance
+     * @throws IOException
+     */
+    public static BasicManagedRepository newFilesystemInstance(String id, String name, Path repositoryPath) throws IOException {
+        FileLockManager lockManager = new DefaultFileLockManager();
+        FilesystemStorage storage = new FilesystemStorage(repositoryPath, lockManager);
+        return new BasicManagedRepository(id, name, storage);
+    }
+
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/BasicManagedRepositoryValidator.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/BasicManagedRepositoryValidator.java
new file mode 100644 (file)
index 0000000..5b9e3a7
--- /dev/null
@@ -0,0 +1,149 @@
+package org.apache.archiva.repository.base.managed;
+/*
+ * 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.registry.Registry;
+import org.apache.archiva.repository.base.ConfigurationHandler;
+import org.apache.archiva.repository.validation.AbstractRepositoryValidator;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.RepositoryRegistry;
+import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationError;
+import org.apache.archiva.repository.validation.ValidationResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.apache.archiva.components.scheduler.CronExpressionValidator;
+
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import static org.apache.archiva.repository.validation.ErrorKeys.*;
+
+/**
+ * Validator for managed repository data.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+@Service( "repositoryValidator#common#managed" )
+public class BasicManagedRepositoryValidator extends AbstractRepositoryValidator<ManagedRepository> implements RepositoryValidator<ManagedRepository>
+{
+    RepositoryRegistry repositoryRegistry;
+    private static final String CATEGORY = "managed_repository";
+    private static final Pattern REPOSITORY_ID_VALID_EXPRESSION_PATTERN = Pattern.compile( REPOSITORY_ID_VALID_EXPRESSION );
+    private static final Pattern REPOSITORY_NAME_VALID_EXPRESSION_PATTERN = Pattern.compile( REPOSITORY_NAME_VALID_EXPRESSION );
+    private static final Pattern REPOSITORY_LOCATION_VALID_EXPRESSION_PATTERN = Pattern.compile( REPOSITORY_LOCATION_VALID_EXPRESSION );
+
+    private final ConfigurationHandler configurationHandler;
+
+
+    public BasicManagedRepositoryValidator( ConfigurationHandler configurationHandler)
+    {
+        super( CATEGORY );
+        this.configurationHandler = configurationHandler;
+    }
+
+    @Override
+    public ValidationResponse<ManagedRepository> apply( ManagedRepository managedRepository, boolean update )
+    {
+        Map<String, List<ValidationError>> errors = null;
+        if (managedRepository==null) {
+            errors = appendError( errors, "id", ISNULL );
+        }
+        final String repoId = managedRepository.getId( );
+        if ( StringUtils.isBlank( repoId ) ) {
+            errors = appendError( errors, "id", ISEMPTY );
+        }
+
+        if (!update)
+        {
+            if ( repositoryRegistry.hasManagedRepository( managedRepository.getId( ) ) )
+            {
+                errors = appendError( errors, "id", MANAGED_REPOSITORY_EXISTS, repoId );
+            }
+            else if ( repositoryRegistry.hasRemoteRepository( repoId ) )
+            {
+                errors = appendError( errors, "id", REMOTE_REPOSITORY_EXISTS, repoId );
+            }
+            else if ( repositoryRegistry.hasRepositoryGroup( repoId ) )
+            {
+                errors = appendError( errors, "id", REPOSITORY_GROUP_EXISTS, repoId );
+            }
+        }
+
+        if ( !REPOSITORY_ID_VALID_EXPRESSION_PATTERN.matcher( repoId ).matches( ) )
+        {
+            errors = appendError( errors, "id", INVALID_CHARS, repoId, new String[]{"alphanumeric", "_", ".", "-"} );
+        }
+        if ( StringUtils.isBlank( managedRepository.getName() ) )
+        {
+            errors = appendError( errors, "name", ISEMPTY );
+        }
+
+        if ( !REPOSITORY_NAME_VALID_EXPRESSION_PATTERN.matcher( managedRepository.getName() ).matches( ) )
+        {
+            errors = appendError( errors, "name", INVALID_CHARS, managedRepository.getName( ), new String[]{"alphanumeric", "whitespace", "/", "(", ")", "_", ".", "-"} );
+        }
+
+        String cronExpression = managedRepository.getSchedulingDefinition( );
+        if ( StringUtils.isNotBlank( cronExpression ) )
+        {
+            CronExpressionValidator validator = new CronExpressionValidator( );
+
+            if ( !validator.validate( cronExpression ) )
+            {
+                errors = appendError( errors, "scheduling_definition", INVALID_SCHEDULING_EXPRESSION, cronExpression );
+            }
+        }
+        // Cron expression may be empty
+
+        String repoLocation = interpolateVars( managedRepository.getLocation( ).toString() );
+
+        if ( !REPOSITORY_LOCATION_VALID_EXPRESSION_PATTERN.matcher( repoLocation ).matches() )
+        {
+            errors = appendError( errors, "location", INVALID_LOCATION, repoLocation, new String[]{"alphanumeric", "=", "?", "!", "&", "/", "\\", "_", ".", ":", "~", "-"} );
+        }
+
+        return new ValidationResponse<>( managedRepository, errors );
+    }
+
+    public String interpolateVars( String directory )
+    {
+        Registry registry = configurationHandler.getArchivaConfiguration( ).getRegistry( );
+        String value = StringUtils.replace( directory, "${appserver.base}",
+            registry.getString( "appserver.base", "${appserver.base}" ) );
+        value = StringUtils.replace( value, "${appserver.home}",
+            registry.getString( "appserver.home", "${appserver.home}" ) );
+        return value;
+    }
+
+
+    @Override
+    public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
+    {
+        this.repositoryRegistry = repositoryRegistry;
+    }
+
+    @Override
+    public Class<ManagedRepository> getFlavour( )
+    {
+        return ManagedRepository.class;
+    }
+
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/ManagedRepositoryHandler.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/ManagedRepositoryHandler.java
new file mode 100644 (file)
index 0000000..3aa65de
--- /dev/null
@@ -0,0 +1,165 @@
+package org.apache.archiva.repository.base.managed;
+/*
+ * 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.configuration.Configuration;
+import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
+import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
+import org.apache.archiva.repository.base.ConfigurationHandler;
+import org.apache.archiva.repository.validation.CheckedResult;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.RepositoryException;
+import org.apache.archiva.repository.RepositoryHandler;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.validation.RepositoryChecker;
+import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationResponse;
+
+import javax.inject.Named;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Handler implementation for managed repositories.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class ManagedRepositoryHandler
+implements RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration>
+{
+
+    public ManagedRepositoryHandler( ArchivaRepositoryRegistry repositoryRegistry,
+                                     ConfigurationHandler configurationHandler,
+                                     @Named( "repositoryValidator#common#managed") RepositoryValidator<ManagedRepository> managedRepositoryValidator )
+    {
+    }
+
+    @Override
+    public Map<String, ManagedRepository> newInstancesFromConfig( )
+    {
+        return null;
+    }
+
+    @Override
+    public ManagedRepository newInstance( RepositoryType type, String id ) throws RepositoryException
+    {
+        return null;
+    }
+
+    @Override
+    public ManagedRepository newInstance( ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
+    {
+        return null;
+    }
+
+    @Override
+    public ManagedRepository put( ManagedRepository repository ) throws RepositoryException
+    {
+        return null;
+    }
+
+    @Override
+    public ManagedRepository put( ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
+    {
+        return null;
+    }
+
+    @Override
+    public ManagedRepository put( ManagedRepositoryConfiguration repositoryConfiguration, Configuration configuration ) throws RepositoryException
+    {
+        return null;
+    }
+
+    @Override
+    public <D> CheckedResult<ManagedRepository, D> putWithCheck( ManagedRepositoryConfiguration repositoryConfiguration, RepositoryChecker<ManagedRepository, D> checker ) throws RepositoryException
+    {
+        return null;
+    }
+
+    @Override
+    public void remove( String id ) throws RepositoryException
+    {
+
+    }
+
+    @Override
+    public void remove( String id, Configuration configuration ) throws RepositoryException
+    {
+
+    }
+
+    @Override
+    public ManagedRepository get( String id )
+    {
+        return null;
+    }
+
+    @Override
+    public ManagedRepository clone( ManagedRepository repo ) throws RepositoryException
+    {
+        return null;
+    }
+
+    @Override
+    public void updateReferences( ManagedRepository repo, ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
+    {
+
+    }
+
+    @Override
+    public Collection<ManagedRepository> getAll( )
+    {
+        return null;
+    }
+
+    @Override
+    public RepositoryValidator<ManagedRepository> getValidator( )
+    {
+        return null;
+    }
+
+    @Override
+    public ValidationResponse<ManagedRepository> validateRepository( ManagedRepository repository )
+    {
+        return null;
+    }
+
+    @Override
+    public ValidationResponse<ManagedRepository> validateRepositoryForUpdate( ManagedRepository repository )
+    {
+        return null;
+    }
+
+    @Override
+    public boolean has( String id )
+    {
+        return false;
+    }
+
+    @Override
+    public void init( )
+    {
+
+    }
+
+    @Override
+    public void close( )
+    {
+
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/remote/AbstractRemoteRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/remote/AbstractRemoteRepository.java
new file mode 100644 (file)
index 0000000..72f2fe8
--- /dev/null
@@ -0,0 +1,160 @@
+package org.apache.archiva.repository.base.remote;
+
+/*
+ * 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.EditableRemoteRepository;
+import org.apache.archiva.repository.RemoteRepositoryContent;
+import org.apache.archiva.repository.RepositoryCredentials;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.base.AbstractRepository;
+import org.apache.archiva.repository.storage.RepositoryStorage;
+
+import java.net.URI;
+import java.time.Duration;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Abstract implementation of a remote repository. Abstract classes must implement the
+ * features and capabilities by themselves.
+ */
+public abstract class AbstractRemoteRepository extends AbstractRepository implements EditableRemoteRepository
+{
+
+    private RepositoryCredentials credentials;
+    private String checkPath;
+    private Map<String,String> extraParameters = new HashMap<>(  );
+    private Map<String,String> uExtraParameters = Collections.unmodifiableMap( extraParameters );
+    private Map<String,String> extraHeaders = new HashMap<>(  );
+    private Map<String,String> uExtraHeaders = Collections.unmodifiableMap( extraHeaders );
+    private Duration timeout = Duration.ofSeconds( 60 );
+    private String proxyId;
+    private RemoteRepositoryContent content;
+
+    public AbstractRemoteRepository( RepositoryType type, String id, String name , RepositoryStorage storage)
+    {
+        super( type, id, name, storage );
+    }
+
+    public AbstractRemoteRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
+    {
+        super( primaryLocale, type, id, name, storage );
+    }
+
+    @Override
+    public void setCredentials( RepositoryCredentials credentials )
+    {
+        this.credentials = credentials;
+    }
+
+    @Override
+    public void setCheckPath( String path )
+    {
+        this.checkPath = path;
+    }
+
+    @Override
+    public void setExtraParameters( Map<String, String> params )
+    {
+        this.extraParameters.clear();
+        this.extraParameters.putAll(params);
+    }
+
+    @Override
+    public void addExtraParameter( String key, String value )
+    {
+        this.extraParameters.put(key, value);
+    }
+
+    @Override
+    public void setExtraHeaders( Map<String, String> headers )
+    {
+        this.extraHeaders.clear();
+        this.extraHeaders.putAll(headers);
+    }
+
+    @Override
+    public void addExtraHeader( String header, String value )
+    {
+        this.extraHeaders.put(header, value);
+    }
+
+    @Override
+    public void setTimeout( Duration duration )
+    {
+        this.timeout = duration;
+    }
+
+    @Override
+    public RemoteRepositoryContent getContent( )
+    {
+        return content;
+    }
+
+    @Override
+    public void setContent(RemoteRepositoryContent content) {
+        this.content = content;
+    }
+
+    @Override
+    public RepositoryCredentials getLoginCredentials( )
+    {
+        return credentials;
+    }
+
+    @Override
+    public String getCheckPath( )
+    {
+        return checkPath;
+    }
+
+    @Override
+    public Map<String, String> getExtraParameters( )
+    {
+        return uExtraParameters;
+    }
+
+    @Override
+    public Map<String, String> getExtraHeaders( )
+    {
+        return uExtraHeaders;
+    }
+
+    @Override
+    public Duration getTimeout( )
+    {
+        return timeout;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        return str.append("checkPath=").append(checkPath)
+                .append(",creds:").append(credentials).toString();
+    }
+
+    @Override
+    public void setLocation(URI location) {
+        // Location of remote repositories is not for the local filestore
+        super.location = location;
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/remote/BasicRemoteRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/remote/BasicRemoteRepository.java
new file mode 100644 (file)
index 0000000..0b6d49b
--- /dev/null
@@ -0,0 +1,95 @@
+package org.apache.archiva.repository.base.remote;
+
+/*
+ * 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.common.filelock.DefaultFileLockManager;
+import org.apache.archiva.common.filelock.FileLockManager;
+import org.apache.archiva.repository.ReleaseScheme;
+import org.apache.archiva.repository.RepositoryCapabilities;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.StandardCapabilities;
+import org.apache.archiva.repository.storage.fs.FilesystemStorage;
+import org.apache.archiva.repository.storage.RepositoryStorage;
+import org.apache.archiva.repository.features.IndexCreationFeature;
+import org.apache.archiva.repository.features.RemoteIndexFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Locale;
+
+/**
+ *
+ * Just a helper class, mainly used for unit tests.
+ *
+ *
+ */
+public class BasicRemoteRepository extends AbstractRemoteRepository
+
+{
+    Logger log = LoggerFactory.getLogger(BasicRemoteRepository.class);
+
+    RemoteIndexFeature remoteIndexFeature = new RemoteIndexFeature();
+    IndexCreationFeature indexCreationFeature = new IndexCreationFeature(true);
+
+
+    static final StandardCapabilities CAPABILITIES = new StandardCapabilities( new ReleaseScheme[] {
+        ReleaseScheme.RELEASE, ReleaseScheme.SNAPSHOT
+    }, new String[] {"default"}, new String[0], new String[] {
+        RemoteIndexFeature.class.toString(),
+            IndexCreationFeature.class.toString()
+    }, true, true, true, true, true  );
+
+    public BasicRemoteRepository( String id, String name, RepositoryStorage storage)
+    {
+        super( RepositoryType.MAVEN, id, name, storage);
+        initFeatures();
+    }
+
+    public BasicRemoteRepository( Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage storage )
+    {
+        super( primaryLocale, type, id, name, storage );
+        initFeatures();
+    }
+
+    private void initFeatures() {
+        addFeature( remoteIndexFeature );
+        addFeature( indexCreationFeature );
+    }
+
+    @Override
+    public boolean hasIndex( )
+    {
+        return true;
+    }
+
+    @Override
+    public RepositoryCapabilities getCapabilities( )
+    {
+        return CAPABILITIES;
+    }
+
+
+    public static BasicRemoteRepository newFilesystemInstance(String id, String name, Path basePath) throws IOException {
+        FileLockManager lockManager = new DefaultFileLockManager();
+        FilesystemStorage storage = new FilesystemStorage(basePath.resolve(id), lockManager);
+        return new BasicRemoteRepository(id, name, storage);
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/validation/CommonGroupValidator.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/validation/CommonGroupValidator.java
deleted file mode 100644 (file)
index f9fd6fd..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.apache.archiva.repository.base.validation;
-/*
- * 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.RepositoryGroup;
-import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.base.ConfigurationHandler;
-import org.apache.archiva.repository.validation.AbstractRepositoryValidator;
-import org.apache.archiva.repository.validation.RepositoryValidator;
-import org.apache.archiva.repository.validation.ValidationError;
-import org.apache.archiva.repository.validation.ValidationResponse;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.stereotype.Service;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- *
- * A validator for repository groups. All validation errors are prefixed with category 'repository_group'.
- *
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Service( "repositoryValidator#common#group" )
-public class CommonGroupValidator extends AbstractRepositoryValidator<RepositoryGroup> implements RepositoryValidator<RepositoryGroup>
-{
-
-    private static final Pattern REPO_GROUP_ID_PATTERN = Pattern.compile( "[A-Za-z0-9\\._\\-]+" );
-    private final ConfigurationHandler configurationHandler;
-
-    private RepositoryRegistry repositoryRegistry;
-
-    public CommonGroupValidator( ConfigurationHandler configurationHandler )
-    {
-        this.configurationHandler = configurationHandler;
-    }
-
-
-    private Map<String, List<ValidationError>> appendError( Map<String, List<ValidationError>> errorMap, String errorKey, Object... parameter )
-    {
-        Map<String, List<ValidationError>> result;
-        result = errorMap == null ? new HashMap<>( ) : errorMap;
-        ValidationError error = ValidationError.ofKey( errorKey, parameter );
-        List<ValidationError> errList = result.computeIfAbsent( error.getAttribute( ), k -> new ArrayList<ValidationError>( ) );
-        errList.add( error );
-        return result;
-    }
-
-    public ValidationResponse apply( RepositoryGroup repositoryGroup, boolean updateMode ) throws IllegalArgumentException
-    {
-        final String repoGroupId = repositoryGroup.getId( );
-        Map<String, List<ValidationError>> errors = null;
-        if ( StringUtils.isBlank( repoGroupId ) )
-        {
-            errors = appendError( errors, "repository_group.id.empty" );
-        }
-
-        if ( repoGroupId.length( ) > 100 )
-        {
-            errors = appendError( errors, "repository_group.id.max_length", repoGroupId, Integer.toString( 100 ) );
-
-        }
-
-        Matcher matcher = REPO_GROUP_ID_PATTERN.matcher( repoGroupId );
-        if ( !matcher.matches( ) )
-        {
-            errors = appendError( errors, "repository_group.id.invalid_chars", "alphanumeric, '.', '-','_'" );
-        }
-
-        if ( repositoryGroup.getMergedIndexTTL( ) <= 0 )
-        {
-            errors = appendError( errors, "repository_group.merged_index_ttl.min", "0" );
-        }
-
-
-        if ( repositoryRegistry != null && !updateMode )
-        {
-            if ( repositoryRegistry.hasRepositoryGroup( repoGroupId ) )
-            {
-                errors = appendError( errors, "repository_group.id.group_exists", repoGroupId );
-            }
-            else if ( repositoryRegistry.hasManagedRepository( repoGroupId ) )
-            {
-                errors = appendError( errors, "repository_group.id.managed_exists" );
-            }
-            else if ( repositoryRegistry.hasRemoteRepository( repoGroupId ) )
-            {
-                errors = appendError( errors, "repository_group.id.remote_exists" );
-            }
-        }
-        return new ValidationResponse(repositoryGroup, errors );
-    }
-
-
-
-
-    public ConfigurationHandler getConfigurationHandler( )
-    {
-        return configurationHandler;
-    }
-
-    public RepositoryRegistry getRepositoryRegistry( )
-    {
-        return repositoryRegistry;
-    }
-
-    @Override
-    public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
-    {
-        this.repositoryRegistry = repositoryRegistry;
-    }
-
-    @Override
-    public Class<RepositoryGroup> getFlavour( )
-    {
-        return RepositoryGroup.class;
-    }
-
-    @Override
-    public boolean isFlavour( Class<?> clazz )
-    {
-        return RepositoryGroup.class.isAssignableFrom( clazz );
-    }
-}
index 00bbbc8c1130e12a79995bec7552ebe4fe805e82..6601ad2c001b3408b65d16e7ff9a523604a8e417 100644 (file)
@@ -30,6 +30,9 @@ import org.apache.archiva.repository.Repository;
 import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/BasicManagedRepositoryValidatorTest.java b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/BasicManagedRepositoryValidatorTest.java
new file mode 100644 (file)
index 0000000..5b950f9
--- /dev/null
@@ -0,0 +1,48 @@
+package org.apache.archiva.repository.base.group;
+
+/*
+ * 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.junit.jupiter.api.Test;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+class BasicManagedRepositoryValidatorTest
+{
+
+    @Test
+    void apply( )
+    {
+    }
+
+    @Test
+    void applyForUpdate( )
+    {
+    }
+
+    @Test
+    void getFlavour( )
+    {
+    }
+
+    @Test
+    void isFlavour( )
+    {
+    }
+}
\ No newline at end of file
index 90dd593e643a3ddbd7881ba2452c94d015bcc85f..c98ba066b4203477d6edcedc1b327ff3a80b22cc 100644 (file)
@@ -30,8 +30,8 @@ import org.apache.archiva.repository.features.ArtifactCleanupFeature;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.RemoteIndexFeature;
 import org.apache.archiva.repository.features.StagingRepositoryFeature;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
 import org.apache.archiva.repository.base.PasswordCredentials;
 import org.springframework.stereotype.Service;
 
index adb5cb0ca294c18f4a855b3e956719703022703e..37989d9b300c2e7b8444c544b42c2468f74e5249 100644 (file)
@@ -23,8 +23,8 @@ import junit.framework.TestCase;
 import org.apache.archiva.configuration.ArchivaConfiguration;
 import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
 import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
 import org.apache.archiva.repository.ManagedRepository;
 import org.apache.archiva.repository.RemoteRepository;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
index 45476eebf1d685877c0bbfe4d83e4ec38cdfd74a..8ac297925919f46a791bdadf5abfcfbe0fd09ae0 100644 (file)
@@ -24,8 +24,8 @@ import org.apache.archiva.common.filelock.DefaultFileLockManager;
 import org.apache.archiva.common.filelock.FileLockManager;
 import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
 import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
 import org.apache.archiva.repository.EditableManagedRepository;
 import org.apache.archiva.repository.EditableRemoteRepository;
 import org.apache.archiva.repository.ManagedRepository;
index e8fc6ce1a0c08e70b95a43ff04033f5d5360ee0f..793a1908e929f5ad1272e431ea5bf58f8a59a91c 100644 (file)
@@ -24,7 +24,7 @@ import org.apache.archiva.indexer.ArchivaIndexingContext;
 import org.apache.archiva.indexer.IndexCreationFailedException;
 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
 import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.RemoteIndexFeature;
 import org.apache.archiva.repository.maven.MavenManagedRepository;
index 575d078ad2108e3c1e35ee5c5a8431b6adf501f1..a5b8f647e8ef4040c50172abd1540c1aea92c5e0 100644 (file)
@@ -31,8 +31,7 @@ import org.apache.archiva.indexer.search.SearchResults;
 import org.apache.archiva.proxy.ProxyRegistry;
 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
 import org.apache.archiva.repository.Repository;
-import org.apache.archiva.repository.base.ConfigurationHandler;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
 import org.apache.commons.lang3.SystemUtils;
index 90093edf0f6bb6111d3b6e784ff0aecb0e25b1ef..112083760cf53bc261432270f2299c894bd969ce 100644 (file)
@@ -23,7 +23,7 @@ import org.apache.archiva.indexer.search.SearchFields;
 import org.apache.archiva.indexer.search.SearchResultHit;
 import org.apache.archiva.indexer.search.SearchResults;
 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.easymock.EasyMock;
 import org.junit.After;
 import org.junit.Test;
index f1aa3eb9bd4b9ecac5b05d4556e042b851ad5b71..124c4d1b3c26d3fb2f4026a342492b4e744de72f 100644 (file)
@@ -24,12 +24,11 @@ import org.apache.archiva.indexer.search.SearchResultLimits;
 import org.apache.archiva.indexer.search.SearchResults;
 import org.apache.archiva.indexer.util.SearchUtil;
 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
 import org.junit.After;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.test.context.ContextConfiguration;
 
 import javax.inject.Inject;
index c442d51681fc5d01a5550713a36379d66cc45c2f..ec1a5319dcd7d4e8a66d7e823e4add3d8b8afee7 100644 (file)
@@ -24,7 +24,7 @@ import org.apache.archiva.configuration.*;
 import org.apache.archiva.policies.*;
 import org.apache.archiva.proxy.model.RepositoryProxyHandler;
 import org.apache.archiva.repository.*;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.storage.StorageAsset;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
 import org.apache.maven.wagon.Wagon;
index c59f0ee5a95a1988f6fee7f437f4c1bd3436f229..a2ab1a299deff5332d3639022f0e90f1d77d9e3d 100644 (file)
@@ -34,7 +34,7 @@ import org.apache.archiva.repository.content.BaseRepositoryContentLayout;
 import org.apache.archiva.repository.ManagedRepository;
 import org.apache.archiva.repository.ManagedRepositoryContent;
 import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.content.Artifact;
 import org.apache.archiva.repository.storage.StorageAsset;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
index fb9fe0b8769936c1da93580984015818df329718..13e45d27b1f43fc24c0787f561c4e35324743246 100644 (file)
@@ -205,4 +205,10 @@ public class MockConfiguration
             return getAppServerBaseDir().resolve("data");
         }
     }
+
+    @Override
+    public Registry getRegistry( )
+    {
+        return null;
+    }
 }
index e30a0f2b3d4fa412f830a8f2822e7dd7713d78fa..73ad62ef40090b2188e7f910b49c808985ff0bcd 100644 (file)
@@ -23,8 +23,8 @@ import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
 import org.apache.archiva.event.EventHandler;
-import org.apache.archiva.repository.base.BasicManagedRepository;
-import org.apache.archiva.repository.base.BasicRemoteRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
+import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
 import org.apache.archiva.repository.EditableManagedRepository;
 import org.apache.archiva.repository.EditableRemoteRepository;
 import org.apache.archiva.repository.EditableRepositoryGroup;
index a09e1e6dfd16d7fcf796e896f18cd60d4d6c48e3..4005b87c2df80c98f398a4bf8fcf1ef09758cb66 100644 (file)
@@ -28,7 +28,7 @@ import org.apache.archiva.repository.RepositoryRequestInfo;
 import org.apache.archiva.repository.RepositoryType;
 import org.apache.archiva.repository.StandardCapabilities;
 import org.apache.archiva.repository.UnsupportedFeatureException;
-import org.apache.archiva.repository.base.AbstractManagedRepository;
+import org.apache.archiva.repository.base.managed.AbstractManagedRepository;
 import org.apache.archiva.repository.features.ArtifactCleanupFeature;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.RepositoryFeature;
index 696eeff5cb72ee71a35cde75ad4e002fbcbf08f9..6c73f65ac81e3d5efe78d8e106ef17bd88f75364 100644 (file)
@@ -8,7 +8,7 @@ import org.apache.archiva.repository.RepositoryCapabilities;
 import org.apache.archiva.repository.RepositoryType;
 import org.apache.archiva.repository.StandardCapabilities;
 import org.apache.archiva.repository.UnsupportedFeatureException;
-import org.apache.archiva.repository.base.AbstractRemoteRepository;
+import org.apache.archiva.repository.base.remote.AbstractRemoteRepository;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.features.RemoteIndexFeature;
 import org.apache.archiva.repository.features.RepositoryFeature;
index 5d2628f8d936a2b9b9206111d2dec49dce035f0e..c1be960f122fd6f296596a9bc69e4df7ff7d1f98 100644 (file)
@@ -26,7 +26,7 @@ import org.apache.archiva.repository.ReleaseScheme;
 import org.apache.archiva.repository.RepositoryCapabilities;
 import org.apache.archiva.repository.RepositoryType;
 import org.apache.archiva.repository.StandardCapabilities;
-import org.apache.archiva.repository.base.AbstractRepositoryGroup;
+import org.apache.archiva.repository.base.group.AbstractRepositoryGroup;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.repository.storage.fs.FilesystemStorage;
 import org.slf4j.Logger;
index 1deadfe38ddc7b70f0a381c431b10ce020f38af1..de7d279ee5bf978a50dd1854bcdbab4496e47d1f 100644 (file)
@@ -41,7 +41,7 @@ import org.apache.archiva.repository.RepositoryGroup;
 import org.apache.archiva.repository.RepositoryProvider;
 import org.apache.archiva.repository.RepositoryType;
 import org.apache.archiva.repository.UnsupportedURIException;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.base.PasswordCredentials;
 import org.apache.archiva.repository.event.RepositoryEvent;
 import org.apache.archiva.repository.features.ArtifactCleanupFeature;
index 6a34278f69c7cedede24cc65a8124419b68a0a35..b63208f045a8b0340007b6799f02cddda63384cd 100644 (file)
@@ -18,6 +18,7 @@ package org.apache.archiva.repository.maven.mock.configuration;
  * under the License.
  */
 
+import org.apache.archiva.components.registry.Registry;
 import org.apache.archiva.components.registry.RegistryException;
 import org.apache.archiva.components.registry.RegistryListener;
 import org.apache.archiva.configuration.ArchivaConfiguration;
@@ -149,4 +150,10 @@ public class StubConfiguration
         }
 
     }
+
+    @Override
+    public Registry getRegistry( )
+    {
+        return null;
+    }
 }
index 78625d7157cb8af22b9fbac7ad064fe944aa9592..f88bd7cc70e29da79cc9ddd2a5d4de7a1f163d9e 100644 (file)
@@ -1,5 +1,6 @@
 package org.apache.archiva.repository.maven.mock.configuration;
 
+import org.apache.archiva.components.registry.Registry;
 import org.apache.archiva.components.registry.RegistryException;
 import org.apache.archiva.components.registry.RegistryListener;
 import org.apache.archiva.configuration.ArchivaConfiguration;
@@ -138,4 +139,10 @@ public class TestConfiguration
             return getAppServerBaseDir().resolve("data");
         }
     }
+
+    @Override
+    public Registry getRegistry( )
+    {
+        return null;
+    }
 }
index d778d5c3bb95690aabdfde8887448d3b9dfa39a3..f8c4a3443cc4d892fc60a6fa4c2296fe3ec3e8dc 100644 (file)
@@ -23,10 +23,10 @@ import junit.framework.TestCase;
 import org.apache.archiva.indexer.ArchivaIndexingContext;
 import org.apache.archiva.indexer.UnsupportedBaseContextException;
 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.ManagedRepository;
 import org.apache.archiva.repository.ReleaseScheme;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.repository.storage.StorageAsset;
 import org.apache.archiva.repository.features.IndexCreationFeature;
 import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
index 443078efb55293db316957b432aa943141ad72a2..edacadf75b69555505682d33a10403451dd5e27a 100644 (file)
@@ -29,7 +29,7 @@ import org.apache.archiva.mock.MockRepositorySessionFactory;
 import org.apache.archiva.components.taskqueue.execution.TaskExecutor;
 import org.apache.archiva.repository.ManagedRepository;
 import org.apache.archiva.repository.RepositoryRegistry;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.scheduler.repository.model.RepositoryTask;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
 import org.junit.After;
index 06c2e4ee65e90acbea94f729b152a4c5fdae9768..8a8f0deb95331361d5f4897519f744b96a64825f 100644 (file)
@@ -47,7 +47,7 @@ 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.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.repository.content.BaseRepositoryContentLayout;
 import org.apache.archiva.repository.content.ContentNotFoundException;
 import org.apache.archiva.repository.content.LayoutException;
index 2d73a53f2deee12cb56846bd2efafc7834a34fbc..4927b2161c12cc68465342dfd5ad479d36327b4c 100644 (file)
@@ -34,19 +34,15 @@ package org.apache.archiva.rest.services.v2;/*
  * under the License.
  */
 
-import org.apache.archiva.components.registry.RegistryException;
 import org.apache.archiva.components.rest.model.PagedResult;
 import org.apache.archiva.components.rest.util.QueryHelper;
-import org.apache.archiva.configuration.Configuration;
-import org.apache.archiva.configuration.IndeterminateConfigurationException;
 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
-import org.apache.archiva.repository.CheckedResult;
+import org.apache.archiva.repository.validation.CheckedResult;
 import org.apache.archiva.repository.EditableRepositoryGroup;
 import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.base.ConfigurationHandler;
 import org.apache.archiva.repository.validation.ValidationError;
-import org.apache.archiva.repository.validation.ValidationResponse;
 import org.apache.archiva.rest.api.model.v2.MergeConfiguration;
 import org.apache.archiva.rest.api.model.v2.RepositoryGroup;
 import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
index 0a35b18528ed5b90392d1504a6ae4d5bfbdbdf1a..28b679a2567478ff2fd7f36d5d40c0a3d26c9ad8 100644 (file)
@@ -28,7 +28,7 @@ import org.apache.archiva.metadata.repository.MetadataRepository;
 import org.apache.archiva.metadata.repository.RepositorySession;
 import org.apache.archiva.metadata.repository.RepositorySessionFactory;
 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.Repository;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.storage.fs.FilesystemStorage;
index a012a538802626cc0b81d60f1f373d331819ad96..ad7ee23a5acd6baf841d5fc66d902ded88b99d39 100644 (file)
@@ -23,7 +23,7 @@ package org.apache.archiva.web.rss;
 import junit.framework.TestCase;
 import org.apache.archiva.common.filelock.DefaultFileLockManager;
 import org.apache.archiva.configuration.ArchivaConfiguration;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.storage.fs.FilesystemStorage;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
index e81e0692b0fb3db3f0dc050062c0cd51e1d16293..49974fd24579e5ee1f993415932d8484f82337ff 100644 (file)
@@ -30,7 +30,7 @@ import org.apache.archiva.indexer.ArchivaIndexingContext;
 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
 import org.apache.archiva.repository.ManagedRepository;
 import org.apache.archiva.repository.RepositoryType;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
 import org.apache.archiva.webdav.httpunit.MkColMethodWebRequest;
 import org.apache.commons.io.FileUtils;
index e2b259c5c8e8e45125bfc014c816a6bacbb21860..8d1bde66d29daa4a48f78f6ae68d89a1bee8be76 100644 (file)
@@ -34,7 +34,7 @@ import org.apache.archiva.configuration.FileTypes;
 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
 import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
 import org.apache.archiva.repository.ManagedRepositoryContent;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.repository.maven.content.MavenContentHelper;
 import org.apache.archiva.repository.maven.metadata.storage.ArtifactMappingProvider;
 import org.apache.archiva.proxy.ProxyRegistry;
index b8310c74017c32db00f463dc41c3b5a312571dd1..a73b2f44873f9561c7295bcfff53cfd4c4f16480 100644 (file)
@@ -35,7 +35,7 @@ import org.apache.archiva.redback.users.User;
 import org.apache.archiva.redback.users.memory.SimpleUser;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.metadata.audit.TestAuditListener;
-import org.apache.archiva.repository.base.RepositoryGroupHandler;
+import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
 import org.apache.archiva.security.ServletAuthenticator;
 import org.apache.archiva.security.common.ArchivaRoleConstants;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
index c3f39cf1628236cc5969166029a09373ca4e1d84..4a81b5fc8456c16bbf8f2dd1d51b4b7496683646 100644 (file)
@@ -28,7 +28,7 @@ import org.apache.archiva.metadata.repository.MetadataRepository;
 import org.apache.archiva.metadata.repository.RepositorySession;
 import org.apache.archiva.metadata.repository.RepositorySessionFactory;
 import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
-import org.apache.archiva.repository.base.BasicManagedRepository;
+import org.apache.archiva.repository.base.managed.BasicManagedRepository;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
 import org.junit.Before;
 import org.junit.Test;