diff options
author | Martin Stockhammer <martin_s@apache.org> | 2021-06-27 11:35:23 +0200 |
---|---|---|
committer | Martin Stockhammer <martin_s@apache.org> | 2021-06-27 11:35:23 +0200 |
commit | e8a70027d8342f78272b471aa0ac963c0a6f89be (patch) | |
tree | 26ff0e859616e117d65103ebbea11ddf50b43c87 /archiva-modules/archiva-base/archiva-repository-api/src | |
parent | a1b92c562fae957e601875e50f87a3ff93fecfd6 (diff) | |
download | archiva-e8a70027d8342f78272b471aa0ac963c0a6f89be.tar.gz archiva-e8a70027d8342f78272b471aa0ac963c0a6f89be.zip |
Changing repository group handling
Diffstat (limited to 'archiva-modules/archiva-base/archiva-repository-api/src')
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( ); + } + } + +} |