1 package org.apache.archiva.repository.base;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.components.registry.RegistryException;
23 import org.apache.archiva.configuration.ArchivaConfiguration;
24 import org.apache.archiva.configuration.Configuration;
25 import org.apache.archiva.configuration.ConfigurationEvent;
26 import org.apache.archiva.configuration.ConfigurationListener;
27 import org.apache.archiva.configuration.IndeterminateConfigurationException;
28 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
29 import org.apache.archiva.configuration.ProxyConnectorConfiguration;
30 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
31 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
32 import org.apache.archiva.event.Event;
33 import org.apache.archiva.event.EventHandler;
34 import org.apache.archiva.event.EventManager;
35 import org.apache.archiva.event.EventType;
36 import org.apache.archiva.indexer.ArchivaIndexManager;
37 import org.apache.archiva.indexer.ArchivaIndexingContext;
38 import org.apache.archiva.indexer.IndexCreationFailedException;
39 import org.apache.archiva.indexer.IndexManagerFactory;
40 import org.apache.archiva.indexer.IndexUpdateFailedException;
41 import org.apache.archiva.repository.CheckedResult;
42 import org.apache.archiva.repository.EditableManagedRepository;
43 import org.apache.archiva.repository.EditableRemoteRepository;
44 import org.apache.archiva.repository.EditableRepository;
45 import org.apache.archiva.repository.ManagedRepository;
46 import org.apache.archiva.repository.RemoteRepository;
47 import org.apache.archiva.repository.Repository;
48 import org.apache.archiva.repository.RepositoryContentFactory;
49 import org.apache.archiva.repository.RepositoryException;
50 import org.apache.archiva.repository.RepositoryGroup;
51 import org.apache.archiva.repository.RepositoryProvider;
52 import org.apache.archiva.repository.RepositoryRegistry;
53 import org.apache.archiva.repository.RepositoryType;
54 import org.apache.archiva.repository.UnsupportedRepositoryTypeException;
55 import org.apache.archiva.repository.base.validation.CommonGroupValidator;
56 import org.apache.archiva.repository.event.LifecycleEvent;
57 import org.apache.archiva.repository.event.RepositoryEvent;
58 import org.apache.archiva.repository.event.RepositoryIndexEvent;
59 import org.apache.archiva.repository.event.RepositoryRegistryEvent;
60 import org.apache.archiva.repository.features.IndexCreationFeature;
61 import org.apache.archiva.repository.features.StagingRepositoryFeature;
62 import org.apache.archiva.repository.metadata.MetadataReader;
63 import org.apache.archiva.repository.storage.StorageAsset;
64 import org.apache.archiva.repository.validation.RepositoryChecker;
65 import org.apache.archiva.repository.validation.RepositoryValidator;
66 import org.apache.archiva.repository.validation.ValidationError;
67 import org.apache.archiva.repository.validation.ValidationResponse;
68 import org.apache.commons.collections4.ListUtils;
69 import org.apache.commons.lang3.StringUtils;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
72 import org.springframework.stereotype.Service;
74 import javax.annotation.PostConstruct;
75 import javax.annotation.PreDestroy;
76 import javax.inject.Inject;
77 import javax.inject.Named;
78 import java.util.ArrayList;
79 import java.util.Collection;
80 import java.util.Collections;
81 import java.util.HashMap;
82 import java.util.HashSet;
83 import java.util.List;
86 import java.util.TreeSet;
87 import java.util.concurrent.atomic.AtomicBoolean;
88 import java.util.concurrent.locks.ReentrantReadWriteLock;
89 import java.util.stream.Collectors;
90 import java.util.stream.Stream;
93 * Registry for repositories. This is the central entry point for repositories. It provides methods for
94 * retrieving, adding and removing repositories.
96 * The modification methods addXX and removeXX persist the changes immediately to the configuration. If the
97 * configuration save fails the changes are rolled back.
103 @Service( "repositoryRegistry" )
104 public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHandler<Event>,
108 private static final Logger log = LoggerFactory.getLogger( RepositoryRegistry.class );
111 * We inject all repository providers
114 List<RepositoryProvider> repositoryProviders;
117 IndexManagerFactory indexManagerFactory;
120 List<MetadataReader> metadataReaderList;
123 @Named( "repositoryContentFactory#default" )
124 RepositoryContentFactory repositoryContentFactory;
127 private final EventManager eventManager;
130 private Map<String, ManagedRepository> managedRepositories = new HashMap<>( );
131 private Map<String, ManagedRepository> uManagedRepository = Collections.unmodifiableMap( managedRepositories );
133 private Map<String, RemoteRepository> remoteRepositories = new HashMap<>( );
134 private Map<String, RemoteRepository> uRemoteRepositories = Collections.unmodifiableMap( remoteRepositories );
136 private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock( );
138 private RepositoryGroupHandler groupHandler;
139 private final Set<RepositoryValidator<? extends Repository>> validators;
140 private final ConfigurationHandler configurationHandler;
143 private AtomicBoolean groups_initalized = new AtomicBoolean( false );
144 private AtomicBoolean managed_initialized = new AtomicBoolean( false );
145 private AtomicBoolean remote_initialized = new AtomicBoolean( false );
148 public ArchivaRepositoryRegistry( ConfigurationHandler configurationHandler, List<RepositoryValidator<? extends Repository>> validatorList )
150 this.eventManager = new EventManager( this );
151 this.configurationHandler = configurationHandler;
152 this.validators = initValidatorList( validatorList );
156 private Set<RepositoryValidator<? extends Repository>> initValidatorList( List<RepositoryValidator<? extends Repository>> validators )
158 TreeSet<RepositoryValidator<? extends Repository>> val = new TreeSet<>( );
159 for (RepositoryValidator<? extends Repository> validator : validators) {
160 val.add( validator );
166 public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration )
168 this.configurationHandler.setArchivaConfiguration( archivaConfiguration );
172 private void initialize( )
174 rwLock.writeLock( ).lock( );
177 log.debug( "Initializing repository registry" );
178 updateManagedRepositoriesFromConfig( );
179 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.MANAGED_REPOS_INITIALIZED, this ) );
180 managed_initialized.set( true );
181 updateRemoteRepositoriesFromConfig( );
182 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.REMOTE_REPOS_INITIALIZED, this ) );
183 remote_initialized.set( true );
185 initializeRepositoryGroups( );
187 for ( RepositoryProvider provider : repositoryProviders )
189 provider.addRepositoryEventHandler( this );
191 this.configurationHandler.addListener( this );
195 rwLock.writeLock( ).unlock( );
197 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.RELOADED, this ) );
198 if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
200 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
204 private void initializeRepositoryGroups( )
206 if ( this.groupHandler != null )
208 this.groupHandler.initializeFromConfig( );
209 this.groups_initalized.set( true );
210 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.GROUPS_INITIALIZED, this ) );
214 public void registerGroupHandler( RepositoryGroupHandler groupHandler )
216 this.groupHandler = groupHandler;
217 initializeRepositoryGroups( );
218 if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
220 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
226 public void destroy( )
228 for ( ManagedRepository rep : managedRepositories.values( ) )
232 managedRepositories.clear( );
233 for ( RemoteRepository repo : remoteRepositories.values( ) )
237 remoteRepositories.clear( );
238 groupHandler.close( );
239 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.DESTROYED, this ) );
243 protected Map<RepositoryType, RepositoryProvider> getRepositoryProviderMap( )
245 Map<RepositoryType, RepositoryProvider> map = new HashMap<>( );
246 if ( repositoryProviders != null )
248 for ( RepositoryProvider provider : repositoryProviders )
250 for ( RepositoryType type : provider.provides( ) )
252 map.put( type, provider );
259 protected RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
261 return repositoryProviders.stream( ).filter( repositoryProvider -> repositoryProvider.provides( ).contains( type ) ).findFirst( ).orElseThrow( ( ) -> new RepositoryException( "Repository type cannot be handled: " + type ) );
265 * Updates the repositories
267 private void updateManagedRepositoriesFromConfig( )
272 Set<String> configRepoIds = new HashSet<>( );
273 List<ManagedRepositoryConfiguration> managedRepoConfigs =
274 configurationHandler.getBaseConfiguration( ).getManagedRepositories( );
276 if ( managedRepoConfigs == null )
281 for ( ManagedRepositoryConfiguration repoConfig : managedRepoConfigs )
283 ManagedRepository repo = putRepository( repoConfig, null );
284 configRepoIds.add( repoConfig.getId( ) );
285 if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
287 StagingRepositoryFeature stagF = repo.getFeature( StagingRepositoryFeature.class ).get( );
288 if ( stagF.getStagingRepository( ) != null )
290 configRepoIds.add( stagF.getStagingRepository( ).getId( ) );
294 List<String> toRemove = managedRepositories.keySet( ).stream( ).filter( id -> !configRepoIds.contains( id ) ).collect( Collectors.toList( ) );
295 for ( String id : toRemove )
297 ManagedRepository removed = managedRepositories.remove( id );
301 catch ( Throwable e )
303 log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
308 private ManagedRepository createNewManagedRepository( RepositoryProvider provider, ManagedRepositoryConfiguration cfg ) throws RepositoryException
310 log.debug( "Creating repo {}", cfg.getId( ) );
311 ManagedRepository repo = provider.createManagedInstance( cfg );
312 repo.registerEventHandler( RepositoryEvent.ANY, this );
313 updateRepositoryReferences( provider, repo, cfg, null );
318 private String getStagingId( String repoId )
320 return repoId + StagingRepositoryFeature.STAGING_REPO_POSTFIX;
323 @SuppressWarnings( "unchecked" )
324 private void updateRepositoryReferences( RepositoryProvider provider, ManagedRepository repo, ManagedRepositoryConfiguration cfg, Configuration configuration ) throws RepositoryException
326 log.debug( "Updating references of repo {}", repo.getId( ) );
327 if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
329 StagingRepositoryFeature feature = repo.getFeature( StagingRepositoryFeature.class ).get( );
330 if ( feature.isStageRepoNeeded( ) && feature.getStagingRepository( ) == null )
332 ManagedRepository stageRepo = getManagedRepository( getStagingId( repo.getId( ) ) );
333 if ( stageRepo == null )
335 stageRepo = getStagingRepository( provider, cfg, configuration );
336 managedRepositories.put( stageRepo.getId( ), stageRepo );
337 if ( configuration != null )
339 replaceOrAddRepositoryConfig( provider.getManagedConfiguration( stageRepo ), configuration );
341 pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, stageRepo ) );
343 feature.setStagingRepository( stageRepo );
346 if ( repo instanceof EditableManagedRepository )
348 EditableManagedRepository editableRepo = (EditableManagedRepository) repo;
349 if ( repo.getContent( ) == null )
351 editableRepo.setContent( repositoryContentFactory.getManagedRepositoryContent( repo ) );
352 editableRepo.getContent( ).setRepository( editableRepo );
354 log.debug( "Index repo: " + repo.hasIndex( ) );
355 if ( repo.hasIndex( ) && ( repo.getIndexingContext( ) == null || !repo.getIndexingContext( ).isOpen( ) ) )
357 log.debug( "Creating indexing context for {}", repo.getId( ) );
358 createIndexingContext( editableRepo );
361 repo.registerEventHandler( RepositoryEvent.ANY, this );
365 public ArchivaIndexManager getIndexManager( RepositoryType type )
367 return indexManagerFactory.getIndexManager( type );
371 public MetadataReader getMetadataReader( final RepositoryType type ) throws UnsupportedRepositoryTypeException
373 if ( metadataReaderList != null )
375 return metadataReaderList.stream( ).filter( mr -> mr.isValidForType( type ) ).findFirst( ).orElseThrow( ( ) -> new UnsupportedRepositoryTypeException( type ) );
379 throw new UnsupportedRepositoryTypeException( type );
383 private void createIndexingContext( EditableRepository editableRepo ) throws RepositoryException
385 if ( editableRepo.supportsFeature( IndexCreationFeature.class ) )
387 ArchivaIndexManager idxManager = getIndexManager( editableRepo.getType( ) );
390 editableRepo.setIndexingContext( idxManager.createContext( editableRepo ) );
391 idxManager.updateLocalIndexPath( editableRepo );
393 catch ( IndexCreationFailedException e )
395 throw new RepositoryException( "Could not create index for repository " + editableRepo.getId( ) + ": " + e.getMessage( ), e );
400 private ManagedRepository getStagingRepository( RepositoryProvider provider, ManagedRepositoryConfiguration baseRepoCfg, Configuration configuration ) throws RepositoryException
402 ManagedRepository stageRepo = getManagedRepository( getStagingId( baseRepoCfg.getId( ) ) );
403 if ( stageRepo == null )
405 stageRepo = provider.createStagingInstance( baseRepoCfg );
406 if ( stageRepo.supportsFeature( StagingRepositoryFeature.class ) )
408 stageRepo.getFeature( StagingRepositoryFeature.class ).get( ).setStageRepoNeeded( false );
410 ManagedRepositoryConfiguration stageCfg = provider.getManagedConfiguration( stageRepo );
411 updateRepositoryReferences( provider, stageRepo, stageCfg, configuration );
417 private void updateRemoteRepositoriesFromConfig( )
421 List<RemoteRepositoryConfiguration> remoteRepoConfigs =
422 configurationHandler.getBaseConfiguration( ).getRemoteRepositories( );
424 if ( remoteRepoConfigs == null )
428 Set<String> repoIds = new HashSet<>( );
429 for ( RemoteRepositoryConfiguration repoConfig : remoteRepoConfigs )
431 putRepository( repoConfig, null );
432 repoIds.add( repoConfig.getId( ) );
435 List<String> toRemove = remoteRepositories.keySet( ).stream( ).filter( id -> !repoIds.contains( id ) ).collect( Collectors.toList( ) );
436 for ( String id : toRemove )
438 RemoteRepository removed = remoteRepositories.remove( id );
443 catch ( Throwable e )
445 log.error( "Could not initialize remote repositories from config: {}", e.getMessage( ), e );
450 private RemoteRepository createNewRemoteRepository( RepositoryProvider provider, RemoteRepositoryConfiguration cfg ) throws RepositoryException
452 log.debug( "Creating remote repo {}", cfg.getId( ) );
453 RemoteRepository repo = provider.createRemoteInstance( cfg );
454 updateRepositoryReferences( provider, repo, cfg, null );
459 private void updateRepositoryReferences( RepositoryProvider provider, RemoteRepository repo, RemoteRepositoryConfiguration cfg, Configuration configuration ) throws RepositoryException
461 if ( repo instanceof EditableRemoteRepository && repo.getContent( ) == null )
463 EditableRemoteRepository editableRepo = (EditableRemoteRepository) repo;
464 editableRepo.setContent( repositoryContentFactory.getRemoteRepositoryContent( repo ) );
465 if ( repo.supportsFeature( IndexCreationFeature.class ) && repo.getIndexingContext( ) == null )
467 createIndexingContext( editableRepo );
470 repo.registerEventHandler( RepositoryEvent.ANY, this );
475 * Returns all repositories that are registered. There is no defined order of the returned repositories.
477 * @return a list of managed and remote repositories
480 public Collection<Repository> getRepositories( )
482 rwLock.readLock( ).lock( );
485 return Stream.concat( managedRepositories.values( ).stream( ), remoteRepositories.values( ).stream( ) ).collect( Collectors.toList( ) );
489 rwLock.readLock( ).unlock( );
494 * Returns only the managed repositories. There is no defined order of the returned repositories.
496 * @return a list of managed repositories
499 public Collection<ManagedRepository> getManagedRepositories( )
501 rwLock.readLock( ).lock( );
504 return uManagedRepository.values( );
508 rwLock.readLock( ).unlock( );
513 * Returns only the remote repositories. There is no defined order of the returned repositories.
515 * @return a list of remote repositories
518 public Collection<RemoteRepository> getRemoteRepositories( )
520 rwLock.readLock( ).lock( );
523 return uRemoteRepositories.values( );
527 rwLock.readLock( ).unlock( );
532 public Collection<RepositoryGroup> getRepositoryGroups( )
534 rwLock.readLock( ).lock( );
537 return groupHandler.getAll( );
541 rwLock.readLock( ).unlock( );
546 * Returns the repository with the given id. The returned repository may be a managed or remote repository.
547 * It returns null, if no repository is registered with the given id.
549 * @param repoId the repository id
550 * @return the repository if found, otherwise null
553 public Repository getRepository( String repoId )
555 rwLock.readLock( ).lock( );
558 log.debug( "getRepository {}", repoId );
559 if ( managedRepositories.containsKey( repoId ) )
561 log.debug( "Managed repo" );
562 return managedRepositories.get( repoId );
564 else if ( remoteRepositories.containsKey( repoId ) )
566 log.debug( "Remote repo" );
567 return remoteRepositories.get( repoId );
569 else if ( groupHandler.has( repoId ) )
571 return groupHandler.get( repoId );
580 rwLock.readLock( ).unlock( );
585 * Convenience method, that returns the managed repository with the given id.
586 * It returns null, if no managed repository is registered with this id.
588 * @param repoId the repository id
589 * @return the managed repository if found, otherwise null
592 public ManagedRepository getManagedRepository( String repoId )
594 rwLock.readLock( ).lock( );
597 return managedRepositories.get( repoId );
601 rwLock.readLock( ).unlock( );
606 * Convenience method, that returns the remote repository with the given id.
607 * It returns null, if no remote repository is registered with this id.
609 * @param repoId the repository id
610 * @return the remote repository if found, otherwise null
613 public RemoteRepository getRemoteRepository( String repoId )
615 rwLock.readLock( ).lock( );
618 return remoteRepositories.get( repoId );
622 rwLock.readLock( ).unlock( );
627 public RepositoryGroup getRepositoryGroup( String groupId )
629 rwLock.readLock( ).lock( );
632 return groupHandler.get( groupId );
636 rwLock.readLock( ).unlock( );
641 public boolean hasRepository( String repoId )
643 return this.managedRepositories.containsKey( repoId ) || this.remoteRepositories.containsKey( repoId ) || groupHandler.has( repoId );
647 public boolean hasManagedRepository( String repoId )
649 return this.managedRepositories.containsKey( repoId );
653 public boolean hasRemoteRepository( String repoId )
655 return this.remoteRepositories.containsKey( repoId );
659 public boolean hasRepositoryGroup( String groupId )
661 return groupHandler.has( groupId );
664 protected void saveConfiguration( Configuration configuration ) throws IndeterminateConfigurationException, RegistryException
666 configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
670 * Adds a new repository to the current list, or replaces the repository definition with
671 * the same id, if it exists already.
672 * The change is saved to the configuration immediately.
674 * @param managedRepository the new repository.
675 * @throws RepositoryException if the new repository could not be saved to the configuration.
678 public ManagedRepository putRepository( ManagedRepository managedRepository ) throws RepositoryException
680 rwLock.writeLock( ).lock( );
683 final String id = managedRepository.getId( );
684 if ( remoteRepositories.containsKey( id ) )
686 throw new RepositoryException( "There exists a remote repository with id " + id + ". Could not update with managed repository." );
688 ManagedRepository originRepo = managedRepositories.put( id, managedRepository );
691 if ( originRepo != null && originRepo != managedRepository )
695 RepositoryProvider provider = getProvider( managedRepository.getType( ) );
696 ManagedRepositoryConfiguration newCfg = provider.getManagedConfiguration( managedRepository );
697 Configuration configuration = configurationHandler.getBaseConfiguration( );
698 updateRepositoryReferences( provider, managedRepository, newCfg, configuration );
699 ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( id );
700 if ( oldCfg != null )
702 configuration.removeManagedRepository( oldCfg );
704 configuration.addManagedRepository( newCfg );
705 saveConfiguration( configuration );
706 if ( originRepo != managedRepository )
708 pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, managedRepository ) );
712 pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, managedRepository ) );
714 return managedRepository;
716 catch ( Exception e )
718 // Rollback only partly, because repository is closed already
719 if ( originRepo != null )
721 managedRepositories.put( id, originRepo );
725 managedRepositories.remove( id );
727 log.error( "Exception during configuration update {}", e.getMessage( ), e );
728 throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ) );
733 rwLock.writeLock( ).unlock( );
738 * Adds a new repository or updates the repository with the same id, if it exists already.
739 * The configuration is saved immediately.
741 * @param managedRepositoryConfiguration the repository configuration
742 * @return the updated or created repository
743 * @throws RepositoryException if an error occurs, or the configuration is not valid.
746 public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration ) throws RepositoryException
748 rwLock.writeLock( ).lock( );
751 final String id = managedRepositoryConfiguration.getId( );
752 final RepositoryType repositoryType = RepositoryType.valueOf( managedRepositoryConfiguration.getType( ) );
753 Configuration configuration = configurationHandler.getBaseConfiguration( );
754 ManagedRepository repo = managedRepositories.get( id );
755 ManagedRepositoryConfiguration oldCfg = repo != null ? getProvider( repositoryType ).getManagedConfiguration( repo ) : null;
756 repo = putRepository( managedRepositoryConfiguration, configuration );
759 saveConfiguration( configuration );
761 catch ( IndeterminateConfigurationException | RegistryException e )
763 if ( oldCfg != null )
765 getProvider( repositoryType ).updateManagedInstance( (EditableManagedRepository) repo, oldCfg );
767 log.error( "Could not save the configuration for repository {}: {}", id, e.getMessage( ), e );
768 throw new RepositoryException( "Could not save the configuration for repository " + id + ": " + e.getMessage( ) );
774 rwLock.writeLock( ).unlock( );
780 * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
781 * the configuration is not saved.
783 * @param managedRepositoryConfiguration the new or changed managed repository configuration
784 * @param configuration the configuration object (may be <code>null</code>)
785 * @return the new or updated repository
786 * @throws RepositoryException if the configuration cannot be saved or updated
789 public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration ) throws RepositoryException
791 rwLock.writeLock( ).lock( );
794 final String id = managedRepositoryConfiguration.getId( );
795 final RepositoryType repoType = RepositoryType.valueOf( managedRepositoryConfiguration.getType( ) );
796 ManagedRepository repo;
797 boolean registeredNew = false;
798 repo = managedRepositories.get( id );
799 if ( repo != null && repo.isOpen( ) )
801 if ( repo instanceof EditableManagedRepository )
803 getProvider( repoType ).updateManagedInstance( (EditableManagedRepository) repo, managedRepositoryConfiguration );
807 throw new RepositoryException( "The repository is not editable " + id );
812 repo = getProvider( repoType ).createManagedInstance( managedRepositoryConfiguration );
813 managedRepositories.put( id, repo );
814 registeredNew = true;
816 updateRepositoryReferences( getProvider( repoType ), repo, managedRepositoryConfiguration, configuration );
817 replaceOrAddRepositoryConfig( managedRepositoryConfiguration, configuration );
820 pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, repo ) );
824 pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, repo ) );
830 rwLock.writeLock( ).unlock( );
836 * Adds a new repository group to the current list, or replaces the repository group definition with
837 * the same id, if it exists already.
838 * The change is saved to the configuration immediately.
840 * @param repositoryGroup the new repository group.
841 * @throws RepositoryException if the new repository group could not be saved to the configuration.
844 public RepositoryGroup putRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
846 rwLock.writeLock( ).lock( );
849 if ( this.groupHandler == null )
851 throw new RepositoryException( "Fatal error. RepositoryGroupHandler not registered!" );
853 return this.groupHandler.put( repositoryGroup );
857 rwLock.writeLock( ).unlock( );
862 * Adds a new repository group or updates the repository with the same id, if it exists already.
863 * The configuration is saved immediately.
865 * @param repositoryGroupConfiguration the repository configuration
866 * @return the updated or created repository
867 * @throws RepositoryException if an error occurs, or the configuration is not valid.
870 public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException
872 rwLock.writeLock( ).lock( );
875 return groupHandler.put( repositoryGroupConfiguration );
879 rwLock.writeLock( ).unlock( );
885 public CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> putRepositoryGroupAndValidate( RepositoryGroupConfiguration repositoryGroupConfiguration )
886 throws RepositoryException
888 rwLock.writeLock( ).lock( );
891 return groupHandler.putWithCheck( repositoryGroupConfiguration, groupHandler.getValidator() );
895 rwLock.writeLock( ).unlock( );
900 * Adds a new repository group or updates the repository group with the same id. The given configuration object is updated, but
901 * the configuration is not saved.
903 * @param repositoryGroupConfiguration The configuration of the new or changed repository group.
904 * @param configuration The configuration object. If it is <code>null</code>, the configuration is not saved.
905 * @return The new or updated repository group
906 * @throws RepositoryException if the configuration cannot be saved or updated
909 public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException
911 rwLock.writeLock( ).lock( );
914 return groupHandler.put( repositoryGroupConfiguration, configuration );
918 rwLock.writeLock( ).unlock( );
922 private void replaceOrAddRepositoryConfig( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration )
924 if ( configuration != null )
926 ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( managedRepositoryConfiguration.getId( ) );
927 if ( oldCfg != null )
929 configuration.removeManagedRepository( oldCfg );
931 configuration.addManagedRepository( managedRepositoryConfiguration );
935 private void replaceOrAddRepositoryConfig( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration )
937 if ( configuration != null )
939 RemoteRepositoryConfiguration oldCfg = configuration.findRemoteRepositoryById( remoteRepositoryConfiguration.getId( ) );
940 if ( oldCfg != null )
942 configuration.removeRemoteRepository( oldCfg );
944 configuration.addRemoteRepository( remoteRepositoryConfiguration );
948 private void replaceOrAddRepositoryConfig( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration )
950 RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( repositoryGroupConfiguration.getId( ) );
951 if ( oldCfg != null )
953 configuration.removeRepositoryGroup( oldCfg );
955 configuration.addRepositoryGroup( repositoryGroupConfiguration );
959 public RemoteRepository putRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException
961 rwLock.writeLock( ).lock( );
964 final String id = remoteRepository.getId( );
965 if ( managedRepositories.containsKey( id ) )
967 throw new RepositoryException( "There exists a managed repository with id " + id + ". Could not update with remote repository." );
969 RemoteRepository originRepo = remoteRepositories.put( id, remoteRepository );
970 RemoteRepositoryConfiguration oldCfg = null;
971 RemoteRepositoryConfiguration newCfg;
974 if ( originRepo != null && originRepo != remoteRepository )
978 final RepositoryProvider provider = getProvider( remoteRepository.getType( ) );
979 newCfg = provider.getRemoteConfiguration( remoteRepository );
980 updateRepositoryReferences( provider, remoteRepository, newCfg, configuration );
981 oldCfg = configuration.findRemoteRepositoryById( id );
982 if ( oldCfg != null )
984 configuration.removeRemoteRepository( oldCfg );
986 configuration.addRemoteRepository( newCfg );
987 if ( remoteRepository != originRepo )
989 pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, remoteRepository ) );
993 pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, remoteRepository ) );
995 return remoteRepository;
997 catch ( Exception e )
1000 if ( originRepo != null )
1002 remoteRepositories.put( id, originRepo );
1006 remoteRepositories.remove( id );
1008 if ( oldCfg != null )
1010 RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( id );
1013 configuration.removeRemoteRepository( cfg );
1014 configuration.addRemoteRepository( oldCfg );
1017 log.error( "Error while adding remote repository {}", e.getMessage( ), e );
1018 throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ) );
1023 rwLock.writeLock( ).unlock( );
1028 * Adds a remote repository, or overwrites the repository definition with the same id, if it exists already.
1029 * The modification is saved to the configuration immediately.
1031 * @param remoteRepository the remote repository to add
1032 * @throws RepositoryException if an error occurs during configuration save
1035 public RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException
1037 rwLock.writeLock( ).lock( );
1040 Configuration configuration = configurationHandler.getBaseConfiguration( );
1043 RemoteRepository repo = putRepository( remoteRepository, configuration );
1044 saveConfiguration( configuration );
1047 catch ( RegistryException | IndeterminateConfigurationException e )
1049 log.error( "Error while saving remote repository {}", e.getMessage( ), e );
1050 throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ) );
1055 rwLock.writeLock( ).unlock( );
1060 * Adds a new repository or updates the repository with the same id, if it exists already.
1061 * The configuration is saved immediately.
1063 * @param remoteRepositoryConfiguration the repository configuration
1064 * @return the updated or created repository
1065 * @throws RepositoryException if an error occurs, or the configuration is not valid.
1068 public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration ) throws RepositoryException
1070 rwLock.writeLock( ).lock( );
1073 final String id = remoteRepositoryConfiguration.getId( );
1074 final RepositoryType repositoryType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType( ) );
1075 Configuration configuration = configurationHandler.getBaseConfiguration( );
1076 RemoteRepository repo = remoteRepositories.get( id );
1077 RemoteRepositoryConfiguration oldCfg = repo != null ? getProvider( repositoryType ).getRemoteConfiguration( repo ) : null;
1078 repo = putRepository( remoteRepositoryConfiguration, configuration );
1081 saveConfiguration( configuration );
1083 catch ( IndeterminateConfigurationException | RegistryException e )
1085 if ( oldCfg != null )
1087 getProvider( repositoryType ).updateRemoteInstance( (EditableRemoteRepository) repo, oldCfg );
1089 log.error( "Could not save the configuration for repository {}: {}", id, e.getMessage( ), e );
1090 throw new RepositoryException( "Could not save the configuration for repository " + id + ": " + e.getMessage( ) );
1096 rwLock.writeLock( ).unlock( );
1102 * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
1103 * the configuration is not saved.
1105 * @param remoteRepositoryConfiguration the new or changed repository configuration
1106 * @param configuration the configuration object
1107 * @return the new or updated repository
1108 * @throws RepositoryException if the configuration cannot be saved or updated
1111 @SuppressWarnings( "unchecked" )
1112 public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration ) throws RepositoryException
1114 rwLock.writeLock( ).lock( );
1117 final String id = remoteRepositoryConfiguration.getId( );
1118 final RepositoryType repoType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType( ) );
1119 RemoteRepository repo;
1120 boolean registeredNew = false;
1121 repo = remoteRepositories.get( id );
1122 if ( repo != null && repo.isOpen( ) )
1124 if ( repo instanceof EditableRemoteRepository )
1126 getProvider( repoType ).updateRemoteInstance( (EditableRemoteRepository) repo, remoteRepositoryConfiguration );
1130 throw new RepositoryException( "The repository is not editable " + id );
1135 repo = getProvider( repoType ).createRemoteInstance( remoteRepositoryConfiguration );
1136 remoteRepositories.put( id, repo );
1137 registeredNew = true;
1139 updateRepositoryReferences( getProvider( repoType ), repo, remoteRepositoryConfiguration, configuration );
1140 replaceOrAddRepositoryConfig( remoteRepositoryConfiguration, configuration );
1141 if ( registeredNew )
1143 pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, repo ) );
1147 pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, repo ) );
1153 rwLock.writeLock( ).unlock( );
1160 public void removeRepository( String repoId ) throws RepositoryException
1162 Repository repo = getRepository( repoId );
1165 removeRepository( repo );
1170 public void removeRepository( Repository repo ) throws RepositoryException
1174 log.warn( "Trying to remove null repository" );
1177 if ( repo instanceof RemoteRepository )
1179 removeRepository( (RemoteRepository) repo );
1181 else if ( repo instanceof ManagedRepository )
1183 removeRepository( (ManagedRepository) repo );
1185 else if ( repo instanceof RepositoryGroup )
1187 removeRepositoryGroup( (RepositoryGroup) repo );
1191 throw new RepositoryException( "Repository type not known: " + repo.getClass( ) );
1196 * Removes a managed repository from the registry and configuration, if it exists.
1197 * The change is saved to the configuration immediately.
1199 * @param managedRepository the managed repository to remove
1200 * @throws RepositoryException if a error occurs during configuration save
1203 public void removeRepository( ManagedRepository managedRepository ) throws RepositoryException
1205 if ( managedRepository == null )
1209 final String id = managedRepository.getId( );
1210 ManagedRepository repo = getManagedRepository( id );
1213 rwLock.writeLock( ).lock( );
1216 repo = managedRepositories.remove( id );
1220 this.groupHandler.removeRepositoryFromGroups( repo );
1221 Configuration configuration = configurationHandler.getBaseConfiguration( );
1222 ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById( id );
1225 configuration.removeManagedRepository( cfg );
1227 saveConfiguration( configuration );
1229 pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
1231 catch ( RegistryException | IndeterminateConfigurationException e )
1234 log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
1235 managedRepositories.put( repo.getId( ), repo );
1236 throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
1240 rwLock.writeLock( ).unlock( );
1247 public void removeRepository( ManagedRepository managedRepository, Configuration configuration ) throws RepositoryException
1249 if ( managedRepository == null )
1253 final String id = managedRepository.getId( );
1254 ManagedRepository repo = getManagedRepository( id );
1257 rwLock.writeLock( ).lock( );
1260 repo = managedRepositories.remove( id );
1264 this.groupHandler.removeRepositoryFromGroups( repo );
1265 ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById( id );
1268 configuration.removeManagedRepository( cfg );
1271 pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
1275 rwLock.writeLock( ).unlock( );
1283 * Removes a repository group from the registry and configuration, if it exists.
1284 * The change is saved to the configuration immediately.
1286 * @param repositoryGroup the repository group to remove
1287 * @throws RepositoryException if a error occurs during configuration save
1290 public void removeRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
1292 if ( repositoryGroup == null )
1296 final String id = repositoryGroup.getId( );
1297 if ( groupHandler.has( id ) )
1299 rwLock.writeLock( ).lock( );
1302 groupHandler.remove( id );
1306 rwLock.writeLock( ).unlock( );
1312 public void removeRepositoryGroup( RepositoryGroup repositoryGroup, Configuration configuration ) throws RepositoryException
1314 if ( repositoryGroup == null )
1318 final String id = repositoryGroup.getId( );
1319 if ( groupHandler.has( id ) )
1321 rwLock.writeLock( ).lock( );
1324 groupHandler.remove( id, configuration );
1328 rwLock.writeLock( ).unlock( );
1333 private void doRemoveRepo( RemoteRepository repo, Configuration configuration )
1336 RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( repo.getId( ) );
1339 configuration.removeRemoteRepository( cfg );
1341 List<ProxyConnectorConfiguration> proxyConnectors = new ArrayList<>( configuration.getProxyConnectors( ) );
1342 for ( ProxyConnectorConfiguration proxyConnector : proxyConnectors )
1344 if ( StringUtils.equals( proxyConnector.getTargetRepoId( ), repo.getId( ) ) )
1346 configuration.removeProxyConnector( proxyConnector );
1352 * Removes the remote repository from the registry and configuration.
1353 * The change is saved to the configuration immediately.
1355 * @param remoteRepository the remote repository to remove
1356 * @throws RepositoryException if a error occurs during configuration save
1359 public void removeRepository( RemoteRepository remoteRepository ) throws RepositoryException
1361 if ( remoteRepository == null )
1365 final String id = remoteRepository.getId( );
1366 RemoteRepository repo = getRemoteRepository( id );
1369 rwLock.writeLock( ).lock( );
1372 repo = remoteRepositories.remove( id );
1375 Configuration configuration = configurationHandler.getBaseConfiguration( );
1376 doRemoveRepo( repo, configuration );
1377 saveConfiguration( configuration );
1379 pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
1381 catch ( RegistryException | IndeterminateConfigurationException e )
1384 log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
1385 remoteRepositories.put( repo.getId( ), repo );
1386 throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
1390 rwLock.writeLock( ).unlock( );
1396 public void removeRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException
1398 if ( remoteRepository == null )
1402 final String id = remoteRepository.getId( );
1403 RemoteRepository repo = getRemoteRepository( id );
1406 rwLock.writeLock( ).lock( );
1409 repo = remoteRepositories.remove( id );
1412 doRemoveRepo( repo, configuration );
1414 pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
1418 rwLock.writeLock( ).unlock( );
1425 * Reloads the registry from the configuration.
1428 public void reload( )
1434 * Resets the indexing context of a given repository.
1436 * @param repository The repository
1437 * @throws IndexUpdateFailedException If the index could not be resetted.
1440 public void resetIndexingContext( Repository repository ) throws IndexUpdateFailedException
1442 if ( repository.hasIndex( ) && repository instanceof EditableRepository )
1444 EditableRepository eRepo = (EditableRepository) repository;
1445 ArchivaIndexingContext newCtx = getIndexManager( repository.getType( ) ).reset( repository.getIndexingContext( ) );
1446 eRepo.setIndexingContext( newCtx );
1452 * Creates a new repository instance with the same settings as this one. The cloned repository is not
1453 * registered or saved to the configuration.
1455 * @param repo The origin repository
1456 * @return The cloned repository.
1458 public ManagedRepository clone( ManagedRepository repo, String newId ) throws RepositoryException
1460 if ( managedRepositories.containsKey( newId ) || remoteRepositories.containsKey( newId ) )
1462 throw new RepositoryException( "The given id exists already " + newId );
1464 RepositoryProvider provider = getProvider( repo.getType( ) );
1465 ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration( repo );
1467 ManagedRepository cloned = provider.createManagedInstance( cfg );
1468 cloned.registerEventHandler( RepositoryEvent.ANY, this );
1473 public <T extends Repository> T clone( T repo, String newId ) throws RepositoryException
1475 if ( repo instanceof RemoteRepository )
1477 return (T) this.clone( (RemoteRepository) repo, newId );
1479 else if ( repo instanceof ManagedRepository )
1481 return (T) this.clone( (ManagedRepository) repo, newId );
1485 throw new RepositoryException( "This repository class is not supported " + repo.getClass( ).getName( ) );
1490 * Creates a new repository instance with the same settings as this one. The cloned repository is not
1491 * registered or saved to the configuration.
1493 * @param repo The origin repository
1494 * @return The cloned repository.
1496 public RemoteRepository clone( RemoteRepository repo, String newId ) throws RepositoryException
1498 if ( managedRepositories.containsKey( newId ) || remoteRepositories.containsKey( newId ) )
1500 throw new RepositoryException( "The given id exists already " + newId );
1502 RepositoryProvider provider = getProvider( repo.getType( ) );
1503 RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration( repo );
1505 RemoteRepository cloned = provider.createRemoteInstance( cfg );
1506 cloned.registerEventHandler( RepositoryEvent.ANY, this );
1511 public Repository getRepositoryOfAsset( StorageAsset asset )
1513 if ( asset instanceof Repository )
1515 return (Repository) asset;
1519 return getRepositories( ).stream( ).filter( r -> r.getRoot( )
1520 .getStorage( ).equals( asset.getStorage( ) ) ).findFirst( ).orElse( null );
1525 public <R extends Repository> ValidationResponse<R> validateRepository( R repository )
1527 Map<String, List<ValidationError>> errorMap = this.validators.stream( )
1528 .filter( ( validator ) -> validator.getType( ).equals( RepositoryType.ALL ) || repository.getType( ).equals( validator.getType( ) ) )
1529 .filter( val -> val.isFlavour( repository.getClass() ))
1530 .flatMap( validator -> ((RepositoryValidator<R>)validator).apply( repository ).getResult().entrySet( ).stream( ) )
1531 .collect( Collectors.toMap(
1532 entry -> entry.getKey( ),
1533 entry -> entry.getValue( ),
1534 ( list1, list2 ) -> ListUtils.union( list1, list2 )
1536 return new ValidationResponse( repository, errorMap );
1540 public <R extends Repository> ValidationResponse<R> validateRepositoryForUpdate( R repository )
1542 Map<String, List<ValidationError>> errorMap = this.validators.stream( )
1543 .filter( ( validator ) -> validator.getType( ).equals( RepositoryType.ALL ) || repository.getType( ).equals( validator.getType( ) ) )
1544 .filter( val -> val.isFlavour( repository.getClass() ))
1545 .flatMap( validator -> ((RepositoryValidator<R>)validator).applyForUpdate( repository ).getResult().entrySet( ).stream( ) )
1546 .collect( Collectors.toMap(
1547 entry -> entry.getKey( ),
1548 entry -> entry.getValue( ),
1549 ( list1, list2 ) -> ListUtils.union( list1, list2 )
1551 return new ValidationResponse( repository, errorMap );
1555 public void configurationEvent( ConfigurationEvent event )
1557 // We ignore the event, if the save was triggered by ourself
1558 if ( !ConfigurationHandler.REGISTRY_EVENT_TAG.equals( event.getTag( ) ) )
1566 public <T extends Event> void registerEventHandler( EventType<T> type, EventHandler<? super T> eventHandler )
1568 eventManager.registerEventHandler( type, eventHandler );
1573 public <T extends Event> void unregisterEventHandler( EventType<T> type, EventHandler<? super T> eventHandler )
1575 eventManager.unregisterEventHandler( type, eventHandler );
1580 public void handle( Event event )
1582 // To avoid event cycles:
1583 if ( sameOriginator( event ) )
1587 if ( event instanceof RepositoryIndexEvent )
1589 handleIndexCreationEvent( (RepositoryIndexEvent) event );
1591 // We propagate all events to our listeners, but with context of repository registry
1595 private void handleIndexCreationEvent( RepositoryIndexEvent event )
1597 RepositoryIndexEvent idxEvent = event;
1598 EditableRepository repo = (EditableRepository) idxEvent.getRepository( );
1601 ArchivaIndexManager idxmgr = getIndexManager( repo.getType( ) );
1602 if ( repo.getIndexingContext( ) != null )
1606 ArchivaIndexingContext newCtx = idxmgr.move( repo.getIndexingContext( ), repo );
1607 repo.setIndexingContext( newCtx );
1608 idxmgr.updateLocalIndexPath( repo );
1611 catch ( IndexCreationFailedException e )
1613 log.error( "Could not move index to new directory: '{}'", e.getMessage( ), e );
1620 ArchivaIndexingContext context = idxmgr.createContext( repo );
1621 repo.setIndexingContext( context );
1622 idxmgr.updateLocalIndexPath( repo );
1624 catch ( IndexCreationFailedException e )
1626 log.error( "Could not create index: '{}'", e.getMessage( ), e );
1632 private boolean sameOriginator( Event event )
1634 if ( event.getSource( ) == this )
1638 else if ( event.hasPreviousEvent( ) )
1640 return sameOriginator( event.getPreviousEvent( ) );
1648 private void pushEvent( Event event )
1650 eventManager.fireEvent( event );