aboutsummaryrefslogtreecommitdiffstats
path: root/archiva-modules/archiva-base/archiva-repository-api/src
diff options
context:
space:
mode:
authorMartin Stockhammer <martin_s@apache.org>2021-06-27 11:35:23 +0200
committerMartin Stockhammer <martin_s@apache.org>2021-06-27 11:35:23 +0200
commite8a70027d8342f78272b471aa0ac963c0a6f89be (patch)
tree26ff0e859616e117d65103ebbea11ddf50b43c87 /archiva-modules/archiva-base/archiva-repository-api/src
parenta1b92c562fae957e601875e50f87a3ff93fecfd6 (diff)
downloadarchiva-e8a70027d8342f78272b471aa0ac963c0a6f89be.tar.gz
archiva-e8a70027d8342f78272b471aa0ac963c0a6f89be.zip
Changing repository group handling
Diffstat (limited to 'archiva-modules/archiva-base/archiva-repository-api/src')
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/CheckedResult.java31
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryHandler.java178
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java287
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryType.java2
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/AbstractRepositoryValidator.java50
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/RepositoryChecker.java36
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/RepositoryValidator.java85
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ValidationError.java186
-rw-r--r--archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ValidationResponse.java110
9 files changed, 956 insertions, 9 deletions
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
new file mode 100644
index 000000000..41961a5e7
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/CheckedResult.java
@@ -0,0 +1,31 @@
+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();
+
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryHandler.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryHandler.java
new file mode 100644
index 000000000..49fc4de12
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryHandler.java
@@ -0,0 +1,178 @@
+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.
+ */
+
+import org.apache.archiva.configuration.Configuration;
+import org.apache.archiva.repository.validation.RepositoryChecker;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ *
+ * This is the generic interface that handles different repository flavours.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public interface RepositoryHandler<R extends Repository, C>
+{
+
+ /**
+ * Creates instances from the archiva configuration. The instances are not registered in the registry.
+ *
+ * @return A map of (repository id, Repository) pairs
+ */
+ Map<String, R> newInstancesFromConfig();
+
+ /**
+ * Creates a new instance without registering and without updating the archiva configuration
+ *
+ * @param type the repository type
+ * @param id the repository identifier
+ * @return the repository instance
+ * @throws RepositoryException if the creation failed
+ */
+ R newInstance(RepositoryType type, String id) throws RepositoryException;
+
+ /**
+ * Creates a new instance and updates the given configuration object.
+ *
+ * @param repositoryConfiguration the configuration instance
+ * @return a newly created instance
+ * @throws RepositoryException if the creation failed
+ */
+ R newInstance( C repositoryConfiguration ) throws RepositoryException;
+
+ /**
+ * Adds the given repository to the registry or replaces a already existing repository in the registry.
+ * If an error occurred during the update, it will revert to the old repository status.
+ *
+ * @param repository the repository
+ * @return the created or updated repository instance
+ * @throws RepositoryException if the update or creation failed
+ */
+ R put( R repository ) throws RepositoryException;
+
+ /**
+ * Adds the repository to the registry, based on the given configuration.
+ * If there is a repository registered with the given id, it is updated.
+ * The archiva configuration is updated. The status is not defined, if an error occurs during update. The
+ * The repository instance is registered and initialized if no error occurs
+ *
+ * @param repositoryConfiguration the repository configuration
+ * @return the updated or created repository instance
+ * @throws RepositoryException if the update or creation failed
+ */
+ R put( C repositoryConfiguration ) throws RepositoryException;
+
+ /**
+ * Adds a repository from the given repository configuration. The changes are stored in
+ * the configuration object. The archiva registry is not updated.
+ * The returned repository instance is a clone of the registered repository instance. It is not registered
+ * and not initialized. References are not updated.
+ *
+ * @param repositoryConfiguration the repository configuration
+ * @param configuration the configuration instance
+ * @return the repository instance that was created or updated
+ * @throws RepositoryException if the update or creation failed
+ */
+ R put( C repositoryConfiguration, Configuration configuration ) throws RepositoryException;
+
+ /**
+ * Adds or updates a repository from the given configuration data. The resulting repository is
+ * checked by the repository checker and the result is returned.
+ * If the checker returns a valid result, the registry is updated and configuration is saved.
+ *
+ * @param repositoryConfiguration the repository configuration
+ * @param checker the checker that validates the repository data
+ * @return the repository and the check result
+ * @throws RepositoryException if the creation or update failed
+ */
+ <D> CheckedResult<R, D>
+ putWithCheck( C repositoryConfiguration, RepositoryChecker<R, D> checker) throws RepositoryException;
+
+ /**
+ * Removes the given repository from the registry and updates references and saves the new configuration.
+ *
+ * @param id The repository identifier
+ * @throws RepositoryException if the repository could not be removed
+ */
+ void remove( final String id ) throws RepositoryException;
+
+ /**
+ * Removes the given repository from the registry and updates only the given configuration instance.
+ * The archiva registry is not updated
+ *
+ * @param id the repository identifier
+ * @param configuration the configuration to update
+ * @throws RepositoryException if the repository could not be removed
+ */
+ void remove( String id, Configuration configuration ) throws RepositoryException;
+
+ /**
+ * Returns the repository with the given identifier or <code>null</code>, if it is not registered.
+ *
+ * @param id the repository id
+ * @return if the retrieval failed
+ */
+ R get( String id );
+
+ /**
+ * Clones a given repository without registering.
+ *
+ * @param repo the repository that should be cloned
+ * @return a newly created instance with the same repository data
+ */
+ R clone(R repo) throws RepositoryException;
+
+ /**
+ * Updates the references and stores updates in the given <code>configuration</code> instance.
+ * The references that are updated depend on the concrete repository subclass <code>R</code>.
+ * This method may register/unregister repositories depending on the implementation. That means there is no simple
+ * way to roll back, if an error occurs.
+ *
+ * @param repo the repository for which references are updated
+ * @param repositoryConfiguration the repository configuration
+ */
+ void updateReferences( R repo, C repositoryConfiguration ) throws RepositoryException;
+
+ /**
+ * Returns all registered repositories.
+ *
+ * @return the list of repositories
+ */
+ Collection<R> getAll();
+
+ /**
+ * Returns <code>true</code>, if the repository is registered with the given id, otherwise <code>false</code>
+ * @param id the repository identifier
+ * @return <code>true</code>, if it is registered, otherwise <code>false</code>
+ */
+ boolean has(String id);
+
+ /**
+ * Initializes
+ */
+ void init();
+
+ /**
+ * Closes the handler
+ */
+ void close();
+
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
index bb6bbc98b..2a5210666 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
@@ -29,23 +29,31 @@ 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.ValidationError;
+import org.apache.archiva.repository.validation.ValidationResponse;
import java.util.Collection;
+import java.util.List;
+import java.util.Map;
/**
* Registry for repositories. This is the central entry point for repositories. It provides methods for
* retrieving, adding and removing repositories.
* <p>
- * The modification methods addXX and removeXX persist the changes immediately to the configuration. If the
+ * The modification methods putXX and removeXX without configuration object persist the changes immediately to the archiva configuration. If the
* configuration save fails the changes are rolled back.
+ * </p>
* <p>
+ * The modification methods with configuration object do only update the given configuration. The configuration is not saved.
+ * </p>
* @author Martin Stockhammer <martin_s@apache.org>
*/
+@SuppressWarnings( "UnusedReturnValue" )
public interface RepositoryRegistry extends EventSource
{
/**
* Set the configuration for the registry
- * @param archivaConfiguration
+ * @param archivaConfiguration the archiva configuration instance
*/
void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration );
@@ -57,7 +65,7 @@ public interface RepositoryRegistry extends EventSource
ArchivaIndexManager getIndexManager( RepositoryType type );
/**
- * Returns the metadatareader for the given repository type
+ * Returns the metadata reader for the given repository type
* @param type the repository type
* @return the metadata reader instance
*/
@@ -75,63 +83,305 @@ public interface RepositoryRegistry extends EventSource
*/
Collection<ManagedRepository> getManagedRepositories( );
+ /**
+ * Returns a collection of all registered remote repositories
+ * @return the collection of remote repositories
+ */
Collection<RemoteRepository> getRemoteRepositories( );
+ /**
+ * Returns a collection of all registered repository groups.
+ *
+ * @return the collection of repository groups
+ */
Collection<RepositoryGroup> getRepositoryGroups( );
+ /**
+ * Returns the repository (managed, remote, group) with the given id
+ * @param repoId the id of the repository
+ * @return the repository or <code>null</code> if no repository with this ID is registered.
+ */
Repository getRepository( String repoId );
+ /**
+ * Returns the managed repository with the given id
+ * @param repoId the id of the repository
+ * @return the managed repository instance or <code>null</code>, if no managed repository with this ID is registered.
+ */
ManagedRepository getManagedRepository( String repoId );
+ /**
+ * Returns the remote repository with the given id
+ * @param repoId the id of the repository
+ * @return the remote repository instance or <code>null</code>, if no remote repository with this ID is registered.
+ */
RemoteRepository getRemoteRepository( String repoId );
+ /**
+ * Returns the repository group with the given id
+ * @param groupId the id of the repository group
+ * @return the repository group instance or <code>null</code>, if no repository group with this ID is registered.
+ */
RepositoryGroup getRepositoryGroup( String groupId );
+ /**
+ * Returns <code>true</code>, if a repository with the given ID is registered, otherwise <code>false</code>
+ * @param repoId the ID of the repository
+ * @return <code>true</code>, if a repository with the given ID is registered, otherwise <code>false</code>
+ */
+ boolean hasRepository(String repoId);
+
+ /**
+ * Returns <code>true</code>, if a managed repository with the given ID is registered, otherwise <code>false</code>
+ * @param repoId the id of the managed repository
+ * @return <code>true</code>, if a managed repository with the given ID is registered, otherwise <code>false</code>
+ */
+ boolean hasManagedRepository(String repoId);
+
+ /**
+ * Returns <code>true</code>, if a remote repository with the given ID is registered, otherwise <code>false</code>
+ * @param repoId the id of the remote repository
+ * @return <code>true</code>, if a remote repository with the given ID is registered, otherwise <code>false</code>
+ */
+ boolean hasRemoteRepository(String repoId);
+
+ /**
+ * Returns <code>true</code>, if a repository group with the given ID is registered, otherwise <code>false</code>
+ * @param groupId the id of the repository group
+ * @return <code>true</code>, if a repository group with the given ID is registered, otherwise <code>false</code>
+ */
+ boolean hasRepositoryGroup( String groupId );
+
+ /**
+ * Adds or updates the given managed repository. If a managed repository with the given id exists already, it is updated
+ * from the data of the given instance. Otherwise a new repository is created and updated by the data of the given instance.
+ *
+ * The archiva configuration is updated and saved after updating the registered repository instance.
+ *
+ * @param managedRepository the managed repository
+ * @return the repository instance, that was created or updated
+ * @throws RepositoryException if an error occurred while creating or updating the instance
+ */
ManagedRepository putRepository( ManagedRepository managedRepository ) throws RepositoryException;
+ /**
+ * Adds or updates the given managed repository. If a managed repository with the given id exists already, it is updated
+ * from the data of the given configuration. Otherwise a new repository is created and updated by the data of the given configuration.
+ *
+ * The archiva configuration is updated and saved after updating the registered repository instance.
+ *
+ * @param managedRepositoryConfiguration the managed repository configuration
+ * @return the repository instance, that was created or updated
+ * @throws RepositoryException if an error occurred while creating or updating the instance
+ */
ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration ) throws RepositoryException;
+ /**
+ * Adds or updates the given managed repository. If a managed repository with the given id exists already, it is updated
+ * from the data of the given configuration. Otherwise a new repository is created and updated by the data of the given configuration.
+ *
+ * This method can be used, if the archiva configuration should not be saved. It will only update the given configuration object.
+ *
+ * @param managedRepositoryConfiguration the managed repository configuration
+ * @param configuration the archiva configuration that is updated
+ * @return the repository instance, that was created or updated
+ * @throws RepositoryException if an error occurred while creating or updating the instance
+ */
ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration ) throws RepositoryException;
+ /**
+ * Adds or updates the given repository group. If a repository group with the given id exists already, it is updated
+ * from the data of the given instance. Otherwise a new repository is created and updated by the data of the given instance.
+ *
+ * The archiva configuration is updated and saved after updating the registered repository instance.
+ *
+ * @param repositoryGroup the repository group
+ * @return the repository instance, that was created or updated
+ * @throws RepositoryException if an error occurred while creating or updating the instance
+ */
RepositoryGroup putRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException;
+ /**
+ * Adds or updates the given repository group. If a repository group with the given id exists already, it is updated
+ * from the data of the given configuration. Otherwise a new repository is created and updated by the data of the given configuration.
+ *
+ * The archiva configuration is updated and saved after updating the registered repository instance.
+ *
+ * @param repositoryGroupConfiguration the repository group configuration
+ * @return the repository instance, that was created or updated
+ * @throws RepositoryException if an error occurred while creating or updating the instance
+ */
RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException;
+
+ /**
+ * This method creates or updates a repository by the given configuration. It uses the <code>validator</code> to check the
+ * result. If the validation is not successful, the repository will not be saved.
+ *
+ * @param configuration the repository configuration
+ * @return the result
+ */
+ CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> putRepositoryGroupAndValidate( RepositoryGroupConfiguration configuration) throws RepositoryException;
+
+ /**
+ * Adds or updates the given repository group. If a repository group with the given id exists already, it is updated
+ * from the data of the given configuration. Otherwise a new repository is created and updated by the data of the given configuration.
+ *
+ * This method can be used, if the archiva configuration should not be saved. It will only update the given configuration object.
+ *
+ * @param repositoryGroupConfiguration the repository group configuration
+ * @param configuration the archiva configuration that is updated
+ * @return the repository instance, that was created or updated
+ * @throws RepositoryException if an error occurred while creating or updating the instance
+ */
RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException;
+ /**
+ * Adds or updates the given remote repository. If a remote repository with the given id exists already, it is updated
+ * from the data of the given instance. Otherwise a new repository is created and updated by the data of the given instance.
+ *
+ * This method can be used, if the archiva configuration should not be saved. It will only update the given configuration object.
+ *
+ * @param remoteRepository the remote repository
+ * @param configuration the configuration that is updated
+ * @return the repository instance, that was created or updated
+ * @throws RepositoryException if an error occurred while creating or updating the instance
+ */
RemoteRepository putRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException;
+ /**
+ * Adds or updates the given remote repository. If a remote repository with the given id exists already, it is updated
+ * from the data of the given instance. Otherwise a new repository is created and updated by the data of the given instance.
+ *
+ * The archiva configuration is updated and saved after updating the registered repository instance.
+ *
+ * @param remoteRepository the remote repository
+ * @return the repository instance, that was created or updated
+ * @throws RepositoryException if an error occurred while creating or updating the instance
+ */
RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException;
+ /**
+ * Adds or updates the given remote repository. If a remote repository with the given id exists already, it is updated
+ * from the data of the given configuration. Otherwise a new repository is created and updated by the data of the given configuration.
+ *
+ * The archiva configuration is updated and saved after updating the registered repository instance.
+ *
+ * @param remoteRepositoryConfiguration the remote repository configuration
+ * @return the repository instance, that was created or updated
+ * @throws RepositoryException if an error occurred while creating or updating the instance
+ */
RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration ) throws RepositoryException;
+ /**
+ * Adds or updates the given remote repository. If a remote repository with the given id exists already, it is updated
+ * from the data of the given configuration. Otherwise a new repository is created and updated by the data of the given configuration.
+ *
+ * This method can be used, if the archiva configuration should not be saved. It will only update the given configuration object.
+ *
+ * @param remoteRepositoryConfiguration the remote repository configuration
+ * @param configuration the archiva configuration where the updated data is stored into
+ * @return the repository instance, that was created or updated
+ * @throws RepositoryException if an error occurred while creating or updating the instance
+ */
RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration ) throws RepositoryException;
+ /**
+ * Removes the repository or repository group with the given id, if it exists. Otherwise, it will do nothing.
+ *
+ * The configuration is updated and saved, if the deletion was successful
+ *
+ * @param repoId the id of the repository or repository group to delete
+ * @throws RepositoryException if the repository deletion failed
+ */
void removeRepository( String repoId ) throws RepositoryException;
+ /**
+ * Removes the given repository.
+ *
+ * The configuration is updated and saved, if the deletion was successful
+ *
+ * @param repo the repository instance that should be deleted
+ * @throws RepositoryException if the repository deletion failed
+ */
void removeRepository( Repository repo ) throws RepositoryException;
+ /**
+ * Removes the given managed repository.
+ *
+ * The configuration is updated and saved, if the deletion was successful
+ *
+ * @param managedRepository the managed repository to remove
+ * @throws RepositoryException if the repository deletion failed
+ */
void removeRepository( ManagedRepository managedRepository ) throws RepositoryException;
+ /**
+ * Removes the given managed repository. The given configuration instance is updated, but the
+ * archiva configuration is not saved.
+ *
+ * @param managedRepository the managed repository to remove
+ * @param configuration the configuration instance to update
+ * @throws RepositoryException if the repository deletion failed
+ */
void removeRepository( ManagedRepository managedRepository, Configuration configuration ) throws RepositoryException;
+ /**
+ * Removes the given repository group.
+ *
+ * The configuration is updated and saved, if the deletion was successful
+ *
+ * @param repositoryGroup the repository group to remove
+ * @throws RepositoryException if the repository deletion failed
+ */
void removeRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException;
+ /**
+ * Removes the given repository group. The given configuration instance is updated, but the
+ * archiva configuration is not saved.
+ *
+ * @param repositoryGroup the repository group to remove
+ * @param configuration the configuration instance to update
+ * @throws RepositoryException if the repository deletion failed
+ */
void removeRepositoryGroup( RepositoryGroup repositoryGroup, Configuration configuration ) throws RepositoryException;
+ /**
+ * Removes the given remote repository.
+ *
+ * The configuration is updated and saved, if the deletion was successful
+ *
+ * @param remoteRepository the remote repository to remove
+ * @throws RepositoryException if the repository deletion failed
+ */
void removeRepository( RemoteRepository remoteRepository ) throws RepositoryException;
+ /**
+ * Removes the given remote repository. The given configuration instance is updated, but the
+ * archiva configuration is not saved.
+ *
+ * @param remoteRepository the remote repository to remove
+ * @param configuration the configuration instance to update
+ * @throws RepositoryException if the repository deletion failed
+ */
void removeRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException;
+ /**
+ * Reloads all repositories and groups from the configuration
+ */
void reload( );
void resetIndexingContext( Repository repository ) throws IndexUpdateFailedException;
- ManagedRepository clone( ManagedRepository repo, String newId ) throws RepositoryException;
-
- <T extends Repository> Repository clone( T repo, String newId ) throws RepositoryException;
-
- RemoteRepository clone( RemoteRepository repo, String newId ) throws RepositoryException;
+ /**
+ * Creates a new repository based on the given repository and with the given new id.
+ * @param repo the repository to copy from
+ * @param newId the new repository id
+ * @param <T> the type of the repository (Manage, Remote or RepositoryGroup)
+ * @return the newly created repository
+ * @throws RepositoryException if the repository could not be created
+ */
+ <T extends Repository> T clone( T repo, String newId ) throws RepositoryException;
/**
* Return the repository that stores the given asset.
@@ -139,4 +389,25 @@ public interface RepositoryRegistry extends EventSource
* @return the repository or <code>null</code> if no matching repository is found
*/
Repository getRepositoryOfAsset( StorageAsset asset );
+
+ /**
+ * 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.
+ */
+ <R extends Repository> 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.
+ */
+ <R extends Repository> ValidationResponse<R> validateRepositoryForUpdate( R repository);
+
}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryType.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryType.java
index f60c65787..b5e8385c1 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryType.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryType.java
@@ -25,5 +25,5 @@ package org.apache.archiva.repository;
*/
public enum RepositoryType {
- MAVEN, NPM
+ ALL, MAVEN, NPM
}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/AbstractRepositoryValidator.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/AbstractRepositoryValidator.java
new file mode 100644
index 000000000..319fc50db
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/AbstractRepositoryValidator.java
@@ -0,0 +1,50 @@
+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.CheckedResult;
+import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryRegistry;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public abstract class AbstractRepositoryValidator<R extends Repository> implements RepositoryValidator<R>
+{
+ protected RepositoryRegistry repositoryRegistry;
+
+ @Override
+ public void setRepositoryRegistry( RepositoryRegistry repositoryRegistry )
+ {
+ this.repositoryRegistry = repositoryRegistry;
+ }
+
+ protected abstract ValidationResponse<R> apply( R repo, boolean update );
+
+ @Override
+ public ValidationResponse<R> apply( R r )
+ {
+ return apply( r, false );
+ }
+
+ @Override
+ public ValidationResponse<R> applyForUpdate( R repo )
+ {
+ return apply( repo, true );
+ }
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/RepositoryChecker.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/RepositoryChecker.java
new file mode 100644
index 000000000..f208d10fe
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/RepositoryChecker.java
@@ -0,0 +1,36 @@
+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.CheckedResult;
+import org.apache.archiva.repository.Repository;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public interface RepositoryChecker<R extends Repository, D> extends Function<R, CheckedResult<R,D>>
+{
+
+ @Override
+ CheckedResult<R,D> apply( R r );
+
+ CheckedResult<R,D> applyForUpdate( R repo );
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/RepositoryValidator.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/RepositoryValidator.java
new file mode 100644
index 000000000..041fe8a48
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/RepositoryValidator.java
@@ -0,0 +1,85 @@
+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 org.apache.archiva.repository.RepositoryType;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * A repository validator validates given repository data against certain rules.
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public interface RepositoryValidator<R extends Repository> extends RepositoryChecker<R, Map<String, List<ValidationError>>>, Comparable<RepositoryValidator<R>>
+{
+
+ int DEFAULT_PRIORITY=1000;
+
+ /**
+ * Returns the repository type for which this validator can be used. If the validator is applicable
+ * to all types, it should return {@link RepositoryType#ALL}
+ *
+ * @return the repository type for which this validator is applicable
+ */
+ default RepositoryType getType() {
+ return RepositoryType.ALL;
+ }
+
+ /**
+ * Returns the priority of this validator. Smaller values mean higher priority.
+ * All common validators have priority {@link #DEFAULT_PRIORITY}
+ *
+ * Validators are called in numerical order of their priority.
+ *
+ * @return
+ */
+ default int getPriority() {
+ return DEFAULT_PRIORITY;
+ }
+
+
+ /**
+ * Orders by priority
+ *
+ * @see Comparable#compareTo(Object)
+ */
+ @Override
+ default int compareTo( RepositoryValidator o ) {
+ if (o==null) {
+ return 1;
+ } else
+ {
+ return this.getPriority( ) - o.getPriority( );
+ }
+ }
+
+ /**
+ * Sets the repository registry to the given instance.
+ * @param repositoryRegistry the repository registry
+ */
+ void setRepositoryRegistry( RepositoryRegistry repositoryRegistry );
+
+ Class<R> getFlavour();
+
+ boolean isFlavour(Class<?> clazz);
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ValidationError.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ValidationError.java
new file mode 100644
index 000000000..22594fbfa
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ValidationError.java
@@ -0,0 +1,186 @@
+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.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Represents a single validation error. A error is defined by a global unique key and has a optional number
+ * of arguments.
+ * <p>
+ * The unique key should represent a category, the attribute and a generic type, separated by '.'
+ * E.g. repository_group.id.empty
+ * </p>
+ * <p>
+ * Categories normally separate errors for different domain types, like managed repository, repository group, maven repository.
+ * <p>
+ * Types define a certain type of error that can be handled similar independent of the attribute or category
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class ValidationError
+{
+ public static final String UNSPECIFIED = "unspecified";
+
+ final String errorKey;
+ final String attribute;
+ final String category;
+ final String type;
+ final List<Object> arguments = new ArrayList<>();
+
+
+ public static ValidationError ofKey( final String errorKey, Object... arguments )
+ {
+ return new ValidationError( errorKey, getCategoryFromKey( errorKey ), getTypeFromKey( errorKey ), getAttributeFromKey( errorKey ),
+ Arrays.asList( arguments ) );
+ }
+
+ public static ValidationError ofKey( String errorKey, List<Object> arguments )
+ {
+ return new ValidationError( errorKey, getCategoryFromKey( errorKey ), getTypeFromKey( errorKey ), getAttributeFromKey( errorKey ),
+ arguments );
+ }
+
+ public ValidationError( String errorKey, String category, String type, String attribute, List<Object> arguments )
+ {
+ if ( StringUtils.isEmpty( errorKey ) )
+ {
+ throw new IllegalArgumentException( "The key of a validation error cannot be empty" );
+ }
+ this.errorKey = errorKey;
+ if ( arguments != null )
+ {
+ this.arguments.addAll( arguments );
+ }
+ this.type = type;
+ this.category = category;
+ this.attribute = attribute;
+ }
+
+ private static String getTypeFromKey( final String errorKey )
+ {
+ return errorKey.contains( "." ) ?
+ StringUtils.substringAfterLast( errorKey, "." ) :
+ UNSPECIFIED;
+ }
+
+ private static String getCategoryFromKey( final String errorKey )
+ {
+ return errorKey.contains( "." ) ?
+ StringUtils.substringBefore( errorKey, "." ) :
+ UNSPECIFIED;
+ }
+
+ private static String getAttributeFromKey( final String errorKey )
+ {
+ return StringUtils.countMatches( errorKey, "." ) >= 2 ?
+ StringUtils.substringBetween( errorKey, "." ) : UNSPECIFIED;
+ }
+
+ /**
+ * Returns the unique key of this validation error. It is best practice for keys to contain the
+ * validation source, the attribute and a unique error definition.
+ * E.g. repository_group.id.empty
+ *
+ * @return
+ */
+ public String getErrorKey( )
+ {
+ return errorKey;
+ }
+
+ /**
+ * Returns the list of arguments stored for this error
+ * @return the list of arguments
+ */
+ public List<Object> getArguments( )
+ {
+ return arguments;
+ }
+
+ /**
+ * Adds the given argument to the list
+ * @param argument the argument to add
+ */
+ public void addArgument( Object argument )
+ {
+ this.arguments.add( argument );
+ }
+
+ /**
+ * Returns the generic error type, this error represents.
+ *
+ * @return the error type or {@link #UNSPECIFIED} if not explicitly set.
+ */
+ public String getType( )
+ {
+ return type;
+ }
+
+ /**
+ * Returns the category of the error.
+ *
+ * @return the category or {@link #UNSPECIFIED} if not explicitly set
+ */
+ public String getCategory( )
+ {
+ return category;
+ }
+
+ /**
+ * Returns the attribute name
+ * @return the attribute name or {@link #UNSPECIFIED} if not explicitly set
+ */
+ public String getAttribute( )
+ {
+ return attribute;
+ }
+
+ @Override
+ public String toString( )
+ {
+ final StringBuilder sb = new StringBuilder( "ValidationError{" );
+ sb.append( "errorKey='" ).append( errorKey ).append( '\'' );
+ sb.append( '}' );
+ return sb.toString( );
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if ( this == o ) return true;
+ if ( o == null || getClass( ) != o.getClass( ) ) return false;
+
+ ValidationError that = (ValidationError) o;
+
+ if ( !errorKey.equals( that.errorKey ) ) return false;
+ return arguments.equals( that.arguments );
+ }
+
+ @Override
+ public int hashCode( )
+ {
+ int result = errorKey.hashCode( );
+ result = 31 * result + arguments.hashCode( );
+ return result;
+ }
+}
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ValidationResponse.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ValidationResponse.java
new file mode 100644
index 000000000..377a3ccb2
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/validation/ValidationResponse.java
@@ -0,0 +1,110 @@
+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.CheckedResult;
+import org.apache.archiva.repository.Repository;
+
+import java.util.ArrayList;
+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.
+ *
+ *
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class ValidationResponse<R extends Repository> implements CheckedResult<R, Map<String, List<ValidationError>>>
+{
+ final boolean valid;
+ final R repository;
+ final Map<String, List<ValidationError>> validationErrors = new HashMap<>( );
+
+
+ public ValidationResponse( R repo, Map<String, List<ValidationError>> errors)
+ {
+ if( errors==null || errors.size()==0 ) {
+ this.valid = true;
+ } else {
+ this.valid = false;
+ validationErrors.putAll( errors );
+ }
+ this.repository = repo;
+ }
+
+ public static <S extends Repository> ValidationResponse<S> getValid( S repository )
+ {
+ return new ValidationResponse<>( repository, null );
+ }
+
+ @Override
+ public R getRepository( )
+ {
+ return repository;
+ }
+
+ /**
+ * Returns true, if the validation was successful and there are not validation errors.
+ * @return <code>true</code>, if the validation was successful, otherwise <code>false</code>
+ */
+ @Override
+ public boolean isValid( )
+ {
+ return valid;
+ }
+
+ @Override
+ public Map<String, List<ValidationError>> getResult( )
+ {
+ return validationErrors;
+ }
+
+
+ /**
+ * Add the given validation error to the list for the given attribute.
+ *
+ * @param attribute the name of the attribute
+ * @param error the error that is added to the list
+ */
+ public void addValidationError(String attribute, ValidationError error) {
+ if (!validationErrors.containsKey( attribute )) {
+ validationErrors.put( attribute, new ArrayList<>( ) );
+ }
+ validationErrors.get( attribute ).add( error );
+ }
+
+ /**
+ * Returns a list of validation errors that are stored for the given attribute. If there are no
+ * errors stored for this attribute, a empty list is returned.
+ *
+ * @param attribute the name of the attribute
+ * @return the list of validation errors
+ */
+ public List<ValidationError> getValidationErrors(String attribute) {
+ if (validationErrors.containsKey( attribute )) {
+ return validationErrors.get( attribute );
+ } else {
+ return Collections.emptyList( );
+ }
+ }
+
+}