| 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.RepositoryState; |
| import org.apache.archiva.repository.base.AbstractRepositoryHandler; |
| 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.RepositoryChecker; |
| import org.apache.archiva.repository.validation.RepositoryValidator; |
| import org.apache.archiva.repository.validation.ValidationError; |
| 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.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Optional; |
| 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 |
| extends AbstractRepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration> |
| 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 |
| * @param repositoryValidatorList the list of validators that are registered |
| */ |
| public RepositoryGroupHandler( ArchivaRepositoryRegistry repositoryRegistry, |
| ConfigurationHandler configurationHandler, |
| @Named( "mergedRemoteIndexesScheduler#default" ) MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler, |
| List<RepositoryValidator<? extends Repository>> repositoryValidatorList |
| ) |
| { |
| this.configurationHandler = configurationHandler; |
| this.mergedRemoteIndexesScheduler = mergedRemoteIndexesScheduler; |
| this.repositoryRegistry = repositoryRegistry; |
| this.validator = getCombinedValidatdor( RepositoryGroup.class, repositoryValidatorList ); |
| } |
| |
| @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 ); |
| } |
| |
| @Override |
| public void initializeFromConfig( ) |
| { |
| this.repositoryGroups.clear( ); |
| this.repositoryGroups.putAll( newInstancesFromConfig( ) ); |
| for ( RepositoryGroup group : this.repositoryGroups.values( ) ) |
| { |
| activateRepository( 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; |
| } |
| |
| @Override |
| public void activateRepository( 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 ); |
| setLastState( repositoryGroup, RepositoryState.INITIALIZED ); |
| } |
| |
| 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 ); |
| if (repositoryGroup instanceof EditableRepository) |
| { |
| ( (EditableRepository) repositoryGroup ).setLastState( RepositoryState.REFERENCES_SET ); |
| } |
| 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 ); |
| setLastState( repositoryGroup, RepositoryState.SAVED ); |
| activateRepository( repositoryGroup ); |
| } |
| finally |
| { |
| configLock.unlock( ); |
| } |
| repositoryGroups.put( id, repositoryGroup ); |
| setLastState( repositoryGroup, RepositoryState.REGISTERED ); |
| 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 ); |
| setLastState( currentRepository, RepositoryState.REFERENCES_SET ); |
| activateRepository( currentRepository ); |
| this.repositoryGroups.put( id, currentRepository ); |
| setLastState( currentRepository, RepositoryState.REGISTERED ); |
| } |
| 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 ); |
| setLastState( oldRepository, RepositoryState.REFERENCES_SET ); |
| activateRepository( oldRepository ); |
| repositoryGroups.put( id, oldRepository ); |
| setLastState( oldRepository, RepositoryState.REGISTERED ); |
| } else { |
| repositoryGroups.remove( id ); |
| } |
| 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 ); |
| setLastState( repo, RepositoryState.CREATED ); |
| } |
| replaceOrAddRepositoryConfig( repositoryGroupConfiguration, configuration ); |
| updateReferences( repo, repositoryGroupConfiguration ); |
| setLastState( repo, RepositoryState.REFERENCES_SET ); |
| 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 ); |
| setLastState( repo, RepositoryState.UNREGISTERED ); |
| } |
| |
| } |
| 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 ); |
| } |
| setLastState( repo, RepositoryState.UNREGISTERED ); |
| } |
| } |
| Iterator<RepositoryGroupConfiguration> cfgIter = configuration.getRepositoryGroups( ).iterator( ); |
| while(cfgIter.hasNext()) { |
| RepositoryGroupConfiguration el = cfgIter.next( ); |
| if (id.equals( el.getId() )) { |
| cfgIter.remove( ); |
| break; |
| } |
| } |
| } |
| |
| @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 ); |
| setLastState( cloned, RepositoryState.CREATED ); |
| return cloned; |
| } |
| |
| @Override |
| public void updateReferences( RepositoryGroup repo, RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException |
| { |
| if ( repo instanceof EditableRepositoryGroup && repositoryConfiguration!=null) |
| { |
| 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 CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> validateRepository( RepositoryGroup repository ) |
| { |
| return this.validator.apply( repository ); |
| |
| } |
| |
| @Override |
| public CheckedResult<RepositoryGroup,Map<String, List<ValidationError>>> validateRepositoryForUpdate( RepositoryGroup repository ) |
| { |
| return this.validator.applyForUpdate( repository ); |
| } |
| @Override |
| public boolean hasRepository( 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( ); |
| } |
| |
| } |