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.AbstractRepositoryConfiguration;
24 import org.apache.archiva.configuration.ArchivaConfiguration;
25 import org.apache.archiva.configuration.Configuration;
26 import org.apache.archiva.configuration.ConfigurationEvent;
27 import org.apache.archiva.configuration.ConfigurationListener;
28 import org.apache.archiva.configuration.IndeterminateConfigurationException;
29 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
30 import org.apache.archiva.configuration.ProxyConnectorConfiguration;
31 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
32 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
33 import org.apache.archiva.event.Event;
34 import org.apache.archiva.event.EventHandler;
35 import org.apache.archiva.event.EventManager;
36 import org.apache.archiva.event.EventType;
37 import org.apache.archiva.indexer.ArchivaIndexManager;
38 import org.apache.archiva.indexer.ArchivaIndexingContext;
39 import org.apache.archiva.indexer.IndexCreationFailedException;
40 import org.apache.archiva.indexer.IndexManagerFactory;
41 import org.apache.archiva.indexer.IndexUpdateFailedException;
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.RepositoryHandler;
52 import org.apache.archiva.repository.RepositoryProvider;
53 import org.apache.archiva.repository.RepositoryRegistry;
54 import org.apache.archiva.repository.RepositoryType;
55 import org.apache.archiva.repository.UnsupportedRepositoryTypeException;
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.CheckedResult;
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 List<RepositoryValidator<? extends Repository>> repositoryValidatorList;
126 @Named( "repositoryContentFactory#default" )
127 RepositoryContentFactory repositoryContentFactory;
130 private boolean ignoreIndexing = false;
132 private final EventManager eventManager;
135 private Map<String, RemoteRepository> remoteRepositories = new HashMap<>( );
136 private Map<String, RemoteRepository> uRemoteRepositories = Collections.unmodifiableMap( remoteRepositories );
138 private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock( );
140 private RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration> groupHandler;
141 private RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration> managedRepositoryHandler;
142 private final Set<RepositoryValidator<? extends Repository>> validators;
143 private final ConfigurationHandler configurationHandler;
146 private AtomicBoolean groups_initalized = new AtomicBoolean( false );
147 private AtomicBoolean managed_initialized = new AtomicBoolean( false );
148 private AtomicBoolean remote_initialized = new AtomicBoolean( false );
151 public ArchivaRepositoryRegistry( ConfigurationHandler configurationHandler, List<RepositoryValidator<? extends Repository>> validatorList )
153 this.eventManager = new EventManager( this );
154 this.configurationHandler = configurationHandler;
155 this.validators = initValidatorList( validatorList );
159 private Set<RepositoryValidator<? extends Repository>> initValidatorList( List<RepositoryValidator<? extends Repository>> validators )
161 TreeSet<RepositoryValidator<? extends Repository>> val = new TreeSet<>( );
162 for ( RepositoryValidator<? extends Repository> validator : validators )
164 val.add( validator );
165 validator.setRepositoryRegistry( this );
171 public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration )
173 this.configurationHandler.setArchivaConfiguration( archivaConfiguration );
177 private void initialize( )
179 rwLock.writeLock( ).lock( );
182 log.debug( "Initializing repository registry" );
183 initializeManagedRepositories();
184 updateRemoteRepositoriesFromConfig( );
185 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.REMOTE_REPOS_INITIALIZED, this ) );
186 remote_initialized.set( true );
188 initializeRepositoryGroups( );
190 for ( RepositoryProvider provider : repositoryProviders )
192 provider.addRepositoryEventHandler( this );
194 this.configurationHandler.addListener( this );
198 rwLock.writeLock( ).unlock( );
200 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.RELOADED, this ) );
201 if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
203 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
207 private void initializeRepositoryGroups( )
209 if ( this.groupHandler != null )
211 this.groupHandler.initializeFromConfig( );
212 this.groups_initalized.set( true );
213 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.GROUPS_INITIALIZED, this ) );
217 private void initializeManagedRepositories( )
219 if ( this.managedRepositoryHandler != null )
221 this.managedRepositoryHandler.initializeFromConfig( );
222 this.managed_initialized.set( true );
223 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.MANAGED_REPOS_INITIALIZED, this ) );
227 public void registerGroupHandler( RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration> groupHandler )
229 this.groupHandler = groupHandler;
230 registerRepositoryHandler( groupHandler );
231 initializeRepositoryGroups( );
232 if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
234 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
238 public void registerManagedRepositoryHandler( RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration> managedRepositoryHandler )
240 this.managedRepositoryHandler = managedRepositoryHandler;
241 registerRepositoryHandler( managedRepositoryHandler );
242 initializeManagedRepositories();
243 if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
245 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
251 public void destroy( )
253 managedRepositoryHandler.close( );
254 for ( RemoteRepository repo : remoteRepositories.values( ) )
258 remoteRepositories.clear( );
259 groupHandler.close( );
260 pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.DESTROYED, this ) );
264 public Map<RepositoryType, RepositoryProvider> getRepositoryProviderMap( )
266 Map<RepositoryType, RepositoryProvider> map = new HashMap<>( );
267 if ( repositoryProviders != null )
269 for ( RepositoryProvider provider : repositoryProviders )
271 for ( RepositoryType type : provider.provides( ) )
273 map.put( type, provider );
280 public RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
282 return repositoryProviders.stream( ).filter( repositoryProvider -> repositoryProvider.provides( ).contains( type ) ).findFirst( ).orElseThrow( ( ) -> new RepositoryException( "Repository type cannot be handled: " + type ) );
286 * Updates the repositories
288 private void updateManagedRepositoriesFromConfig( )
290 managedRepositoryHandler.initializeFromConfig( );
294 private String getStagingId( String repoId )
296 return repoId + StagingRepositoryFeature.STAGING_REPO_POSTFIX;
301 public ArchivaIndexManager getIndexManager( RepositoryType type )
303 return indexManagerFactory.getIndexManager( type );
307 public MetadataReader getMetadataReader( final RepositoryType type ) throws UnsupportedRepositoryTypeException
309 if ( metadataReaderList != null )
311 return metadataReaderList.stream( ).filter( mr -> mr.isValidForType( type ) ).findFirst( ).orElseThrow( ( ) -> new UnsupportedRepositoryTypeException( type ) );
315 throw new UnsupportedRepositoryTypeException( type );
319 private void createIndexingContext( EditableRepository editableRepo ) throws RepositoryException
321 if ( editableRepo.supportsFeature( IndexCreationFeature.class ) )
323 ArchivaIndexManager idxManager = getIndexManager( editableRepo.getType( ) );
326 editableRepo.setIndexingContext( idxManager.createContext( editableRepo ) );
327 idxManager.updateLocalIndexPath( editableRepo );
329 catch ( IndexCreationFailedException e )
331 throw new RepositoryException( "Could not create index for repository " + editableRepo.getId( ) + ": " + e.getMessage( ), e );
337 private void updateRemoteRepositoriesFromConfig( )
341 List<RemoteRepositoryConfiguration> remoteRepoConfigs =
342 configurationHandler.getBaseConfiguration( ).getRemoteRepositories( );
344 if ( remoteRepoConfigs == null )
348 Set<String> repoIds = new HashSet<>( );
349 for ( RemoteRepositoryConfiguration repoConfig : remoteRepoConfigs )
351 putRepository( repoConfig, null );
352 repoIds.add( repoConfig.getId( ) );
355 List<String> toRemove = remoteRepositories.keySet( ).stream( ).filter( id -> !repoIds.contains( id ) ).collect( Collectors.toList( ) );
356 for ( String id : toRemove )
358 RemoteRepository removed = remoteRepositories.remove( id );
363 catch ( Throwable e )
365 log.error( "Could not initialize remote repositories from config: {}", e.getMessage( ), e );
370 private RemoteRepository createNewRemoteRepository( RepositoryProvider provider, RemoteRepositoryConfiguration cfg ) throws RepositoryException
372 log.debug( "Creating remote repo {}", cfg.getId( ) );
373 RemoteRepository repo = provider.createRemoteInstance( cfg );
374 updateRepositoryReferences( provider, repo, cfg, null );
379 private void updateRepositoryReferences( RepositoryProvider provider, RemoteRepository repo, RemoteRepositoryConfiguration cfg, Configuration configuration ) throws RepositoryException
381 if ( repo instanceof EditableRemoteRepository && repo.getContent( ) == null )
383 EditableRemoteRepository editableRepo = (EditableRemoteRepository) repo;
384 editableRepo.setContent( repositoryContentFactory.getRemoteRepositoryContent( repo ) );
385 if ( repo.supportsFeature( IndexCreationFeature.class ) && repo.getIndexingContext( ) == null )
387 createIndexingContext( editableRepo );
390 repo.registerEventHandler( RepositoryEvent.ANY, this );
395 * Returns all repositories that are registered. There is no defined order of the returned repositories.
397 * @return a list of managed and remote repositories
400 public Collection<Repository> getRepositories( )
402 rwLock.readLock( ).lock( );
405 return Stream.concat( managedRepositoryHandler.getAll().stream( ), remoteRepositories.values( ).stream( ) ).collect( Collectors.toList( ) );
409 rwLock.readLock( ).unlock( );
414 * Returns only the managed repositories. There is no defined order of the returned repositories.
416 * @return a list of managed repositories
419 public Collection<ManagedRepository> getManagedRepositories( )
421 rwLock.readLock( ).lock( );
424 return managed_initialized.get() ? managedRepositoryHandler.getAll( ) : Collections.emptyList();
428 rwLock.readLock( ).unlock( );
433 * Returns only the remote repositories. There is no defined order of the returned repositories.
435 * @return a list of remote repositories
438 public Collection<RemoteRepository> getRemoteRepositories( )
440 rwLock.readLock( ).lock( );
443 return uRemoteRepositories.values( );
447 rwLock.readLock( ).unlock( );
452 public Collection<RepositoryGroup> getRepositoryGroups( )
454 rwLock.readLock( ).lock( );
457 return groupHandler.getAll( );
461 rwLock.readLock( ).unlock( );
466 * Returns the repository with the given id. The returned repository may be a managed or remote repository.
467 * It returns null, if no repository is registered with the given id.
469 * @param repoId the repository id
470 * @return the repository if found, otherwise null
473 public Repository getRepository( String repoId )
475 rwLock.readLock( ).lock( );
478 log.debug( "getRepository {}", repoId );
479 if ( managedRepositoryHandler.hasRepository( repoId ) )
481 log.debug( "Managed repo" );
482 return managedRepositoryHandler.get( repoId );
484 else if ( remoteRepositories.containsKey( repoId ) )
486 log.debug( "Remote repo" );
487 return remoteRepositories.get( repoId );
489 else if ( groupHandler.hasRepository( repoId ) )
491 return groupHandler.get( repoId );
500 rwLock.readLock( ).unlock( );
505 * Convenience method, that returns the managed repository with the given id.
506 * It returns null, if no managed repository is registered with this id.
508 * @param repoId the repository id
509 * @return the managed repository if found, otherwise null
512 public ManagedRepository getManagedRepository( String repoId )
514 rwLock.readLock( ).lock( );
517 return managed_initialized.get() ? managedRepositoryHandler.get( repoId ) : null;
521 rwLock.readLock( ).unlock( );
526 * Convenience method, that returns the remote repository with the given id.
527 * It returns null, if no remote repository is registered with this id.
529 * @param repoId the repository id
530 * @return the remote repository if found, otherwise null
533 public RemoteRepository getRemoteRepository( String repoId )
535 rwLock.readLock( ).lock( );
538 return remoteRepositories.get( repoId );
542 rwLock.readLock( ).unlock( );
547 public RepositoryGroup getRepositoryGroup( String groupId )
549 rwLock.readLock( ).lock( );
552 return groupHandler.get( groupId );
556 rwLock.readLock( ).unlock( );
561 public boolean hasRepository( String repoId )
563 return ( managedRepositoryHandler != null && managedRepositoryHandler.hasRepository( repoId ) )
564 || ( this.remoteRepositories != null && this.remoteRepositories.containsKey( repoId ) )
565 || ( this.groupHandler != null && groupHandler.hasRepository( repoId ) );
569 public boolean hasManagedRepository( String repoId )
571 return managedRepositoryHandler.hasRepository( repoId );
575 public boolean hasRemoteRepository( String repoId )
577 return this.remoteRepositories.containsKey( repoId );
581 public boolean hasRepositoryGroup( String groupId )
583 return this.groupHandler != null && groupHandler.hasRepository( groupId );
586 protected void saveConfiguration( Configuration configuration ) throws IndeterminateConfigurationException, RegistryException
588 configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
592 * Adds a new repository to the current list, or replaces the repository definition with
593 * the same id, if it exists already.
594 * The change is saved to the configuration immediately.
596 * @param managedRepository the new repository.
597 * @throws RepositoryException if the new repository could not be saved to the configuration.
600 public ManagedRepository putRepository( ManagedRepository managedRepository ) throws RepositoryException
602 rwLock.writeLock( ).lock( );
605 return managed_initialized.get() ? managedRepositoryHandler.put( managedRepository ) : null;
609 rwLock.writeLock( ).unlock( );
614 * Adds a new repository or updates the repository with the same id, if it exists already.
615 * The configuration is saved immediately.
617 * @param managedRepositoryConfiguration the repository configuration
618 * @return the updated or created repository
619 * @throws RepositoryException if an error occurs, or the configuration is not valid.
622 public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration ) throws RepositoryException
624 rwLock.writeLock( ).lock( );
627 return managedRepositoryHandler.put( managedRepositoryConfiguration );
631 rwLock.writeLock( ).unlock( );
637 * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
638 * the configuration is not saved.
640 * @param managedRepositoryConfiguration the new or changed managed repository configuration
641 * @param configuration the configuration object (may be <code>null</code>)
642 * @return the new or updated repository
643 * @throws RepositoryException if the configuration cannot be saved or updated
646 public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration ) throws RepositoryException
648 rwLock.writeLock( ).lock( );
651 return managedRepositoryHandler.put( managedRepositoryConfiguration, configuration );
655 rwLock.writeLock( ).unlock( );
661 * Adds a new repository group to the current list, or replaces the repository group definition with
662 * the same id, if it exists already.
663 * The change is saved to the configuration immediately.
665 * @param repositoryGroup the new repository group.
666 * @throws RepositoryException if the new repository group could not be saved to the configuration.
669 public RepositoryGroup putRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
671 rwLock.writeLock( ).lock( );
674 if ( this.groupHandler == null )
676 throw new RepositoryException( "Fatal error. RepositoryGroupHandler not registered!" );
678 return this.groupHandler.put( repositoryGroup );
682 rwLock.writeLock( ).unlock( );
687 * Adds a new repository group or updates the repository with the same id, if it exists already.
688 * The configuration is saved immediately.
690 * @param repositoryGroupConfiguration the repository configuration
691 * @return the updated or created repository
692 * @throws RepositoryException if an error occurs, or the configuration is not valid.
695 public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException
697 rwLock.writeLock( ).lock( );
700 return groupHandler.put( repositoryGroupConfiguration );
704 rwLock.writeLock( ).unlock( );
710 public CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> putRepositoryGroupAndValidate( RepositoryGroupConfiguration repositoryGroupConfiguration )
711 throws RepositoryException
713 rwLock.writeLock( ).lock( );
716 return groupHandler.putWithCheck( repositoryGroupConfiguration, groupHandler.getValidator( ) );
720 rwLock.writeLock( ).unlock( );
725 * Adds a new repository group or updates the repository group with the same id. The given configuration object is updated, but
726 * the configuration is not saved.
728 * @param repositoryGroupConfiguration The configuration of the new or changed repository group.
729 * @param configuration The configuration object. If it is <code>null</code>, the configuration is not saved.
730 * @return The new or updated repository group
731 * @throws RepositoryException if the configuration cannot be saved or updated
734 public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException
736 rwLock.writeLock( ).lock( );
739 return groupHandler.put( repositoryGroupConfiguration, configuration );
743 rwLock.writeLock( ).unlock( );
747 private void replaceOrAddRepositoryConfig( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration )
749 if ( configuration != null )
751 RemoteRepositoryConfiguration oldCfg = configuration.findRemoteRepositoryById( remoteRepositoryConfiguration.getId( ) );
752 if ( oldCfg != null )
754 configuration.removeRemoteRepository( oldCfg );
756 configuration.addRemoteRepository( remoteRepositoryConfiguration );
761 public RemoteRepository putRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException
763 rwLock.writeLock( ).lock( );
766 final String id = remoteRepository.getId( );
767 if ( managedRepositoryHandler.hasRepository( id ) )
769 throw new RepositoryException( "There exists a managed repository with id " + id + ". Could not update with remote repository." );
771 RemoteRepository originRepo = remoteRepositories.put( id, remoteRepository );
772 RemoteRepositoryConfiguration oldCfg = null;
773 RemoteRepositoryConfiguration newCfg;
776 if ( originRepo != null && originRepo != remoteRepository )
780 final RepositoryProvider provider = getProvider( remoteRepository.getType( ) );
781 newCfg = provider.getRemoteConfiguration( remoteRepository );
782 updateRepositoryReferences( provider, remoteRepository, newCfg, configuration );
783 oldCfg = configuration.findRemoteRepositoryById( id );
784 if ( oldCfg != null )
786 configuration.removeRemoteRepository( oldCfg );
788 configuration.addRemoteRepository( newCfg );
789 if ( remoteRepository != originRepo )
791 pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, remoteRepository ) );
795 pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, remoteRepository ) );
797 return remoteRepository;
799 catch ( Exception e )
802 if ( originRepo != null )
804 remoteRepositories.put( id, originRepo );
808 remoteRepositories.remove( id );
810 if ( oldCfg != null )
812 RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( id );
815 configuration.removeRemoteRepository( cfg );
816 configuration.addRemoteRepository( oldCfg );
819 log.error( "Error while adding remote repository {}", e.getMessage( ), e );
820 throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ) );
825 rwLock.writeLock( ).unlock( );
830 * Adds a remote repository, or overwrites the repository definition with the same id, if it exists already.
831 * The modification is saved to the configuration immediately.
833 * @param remoteRepository the remote repository to add
834 * @throws RepositoryException if an error occurs during configuration save
837 public RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException
839 rwLock.writeLock( ).lock( );
842 Configuration configuration = configurationHandler.getBaseConfiguration( );
845 RemoteRepository repo = putRepository( remoteRepository, configuration );
846 saveConfiguration( configuration );
849 catch ( RegistryException | IndeterminateConfigurationException e )
851 log.error( "Error while saving remote repository {}", e.getMessage( ), e );
852 throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ) );
857 rwLock.writeLock( ).unlock( );
862 * Adds a new repository or updates the repository with the same id, if it exists already.
863 * The configuration is saved immediately.
865 * @param remoteRepositoryConfiguration 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 RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration ) throws RepositoryException
872 rwLock.writeLock( ).lock( );
875 final String id = remoteRepositoryConfiguration.getId( );
876 final RepositoryType repositoryType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType( ) );
877 Configuration configuration = configurationHandler.getBaseConfiguration( );
878 RemoteRepository repo = remoteRepositories.get( id );
879 RemoteRepositoryConfiguration oldCfg = repo != null ? getProvider( repositoryType ).getRemoteConfiguration( repo ) : null;
880 repo = putRepository( remoteRepositoryConfiguration, configuration );
883 saveConfiguration( configuration );
885 catch ( IndeterminateConfigurationException | RegistryException e )
887 if ( oldCfg != null )
889 getProvider( repositoryType ).updateRemoteInstance( (EditableRemoteRepository) repo, oldCfg );
891 log.error( "Could not save the configuration for repository {}: {}", id, e.getMessage( ), e );
892 throw new RepositoryException( "Could not save the configuration for repository " + id + ": " + e.getMessage( ) );
898 rwLock.writeLock( ).unlock( );
904 * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
905 * the configuration is not saved.
907 * @param remoteRepositoryConfiguration the new or changed repository configuration
908 * @param configuration the configuration object
909 * @return the new or updated repository
910 * @throws RepositoryException if the configuration cannot be saved or updated
913 @SuppressWarnings( "unchecked" )
914 public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration ) throws RepositoryException
916 rwLock.writeLock( ).lock( );
919 final String id = remoteRepositoryConfiguration.getId( );
920 final RepositoryType repoType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType( ) );
921 RemoteRepository repo;
922 boolean registeredNew = false;
923 repo = remoteRepositories.get( id );
924 if ( repo != null && repo.isOpen( ) )
926 if ( repo instanceof EditableRemoteRepository )
928 getProvider( repoType ).updateRemoteInstance( (EditableRemoteRepository) repo, remoteRepositoryConfiguration );
932 throw new RepositoryException( "The repository is not editable " + id );
937 repo = getProvider( repoType ).createRemoteInstance( remoteRepositoryConfiguration );
938 remoteRepositories.put( id, repo );
939 registeredNew = true;
941 updateRepositoryReferences( getProvider( repoType ), repo, remoteRepositoryConfiguration, configuration );
942 replaceOrAddRepositoryConfig( remoteRepositoryConfiguration, configuration );
945 pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, repo ) );
949 pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, repo ) );
955 rwLock.writeLock( ).unlock( );
962 public void removeRepository( String repoId ) throws RepositoryException
964 Repository repo = getRepository( repoId );
967 removeRepository( repo );
972 public void removeRepository( Repository repo ) throws RepositoryException
976 log.warn( "Trying to remove null repository" );
979 if ( repo instanceof RemoteRepository )
981 removeRepository( (RemoteRepository) repo );
983 else if ( repo instanceof ManagedRepository )
985 removeRepository( (ManagedRepository) repo );
987 else if ( repo instanceof RepositoryGroup )
989 removeRepositoryGroup( (RepositoryGroup) repo );
993 throw new RepositoryException( "Repository type not known: " + repo.getClass( ) );
998 * Removes a managed repository from the registry and configuration, if it exists.
999 * The change is saved to the configuration immediately.
1001 * @param managedRepository the managed repository to remove
1002 * @throws RepositoryException if a error occurs during configuration save
1005 public void removeRepository( ManagedRepository managedRepository ) throws RepositoryException
1007 if ( managedRepository == null )
1011 rwLock.writeLock( ).lock( );
1014 if (managed_initialized.get() ) managedRepositoryHandler.remove( managedRepository.getId( ) );
1018 rwLock.writeLock( ).unlock( );
1024 public void removeRepository( ManagedRepository managedRepository, Configuration configuration ) throws RepositoryException
1026 if ( managedRepository == null )
1030 rwLock.writeLock( ).lock( );
1033 if (managed_initialized.get()) managedRepositoryHandler.remove( managedRepository.getId( ), configuration );
1037 rwLock.writeLock( ).unlock( );
1044 * Removes a repository group from the registry and configuration, if it exists.
1045 * The change is saved to the configuration immediately.
1047 * @param repositoryGroup the repository group to remove
1048 * @throws RepositoryException if a error occurs during configuration save
1051 public void removeRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
1053 if ( repositoryGroup == null )
1057 final String id = repositoryGroup.getId( );
1058 if ( groupHandler.hasRepository( id ) )
1060 rwLock.writeLock( ).lock( );
1063 groupHandler.remove( id );
1067 rwLock.writeLock( ).unlock( );
1073 public void removeRepositoryGroup( RepositoryGroup repositoryGroup, Configuration configuration ) throws RepositoryException
1075 if ( repositoryGroup == null )
1079 final String id = repositoryGroup.getId( );
1080 if ( groupHandler.hasRepository( id ) )
1082 rwLock.writeLock( ).lock( );
1085 groupHandler.remove( id, configuration );
1089 rwLock.writeLock( ).unlock( );
1094 private void doRemoveRepo( RemoteRepository repo, Configuration configuration )
1097 RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( repo.getId( ) );
1100 configuration.removeRemoteRepository( cfg );
1102 List<ProxyConnectorConfiguration> proxyConnectors = new ArrayList<>( configuration.getProxyConnectors( ) );
1103 for ( ProxyConnectorConfiguration proxyConnector : proxyConnectors )
1105 if ( StringUtils.equals( proxyConnector.getTargetRepoId( ), repo.getId( ) ) )
1107 configuration.removeProxyConnector( proxyConnector );
1113 * Removes the remote repository from the registry and configuration.
1114 * The change is saved to the configuration immediately.
1116 * @param remoteRepository the remote repository to remove
1117 * @throws RepositoryException if a error occurs during configuration save
1120 public void removeRepository( RemoteRepository remoteRepository ) throws RepositoryException
1122 if ( remoteRepository == null )
1126 final String id = remoteRepository.getId( );
1127 RemoteRepository repo = getRemoteRepository( id );
1130 rwLock.writeLock( ).lock( );
1133 repo = remoteRepositories.remove( id );
1136 Configuration configuration = configurationHandler.getBaseConfiguration( );
1137 doRemoveRepo( repo, configuration );
1138 saveConfiguration( configuration );
1140 pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
1142 catch ( RegistryException | IndeterminateConfigurationException e )
1145 log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
1146 remoteRepositories.put( repo.getId( ), repo );
1147 throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
1151 rwLock.writeLock( ).unlock( );
1157 public void removeRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException
1159 if ( remoteRepository == null )
1163 final String id = remoteRepository.getId( );
1164 RemoteRepository repo = getRemoteRepository( id );
1167 rwLock.writeLock( ).lock( );
1170 repo = remoteRepositories.remove( id );
1173 doRemoveRepo( repo, configuration );
1175 pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
1179 rwLock.writeLock( ).unlock( );
1186 * Reloads the registry from the configuration.
1189 public void reload( )
1195 * Resets the indexing context of a given repository.
1197 * @param repository The repository
1198 * @throws IndexUpdateFailedException If the index could not be resetted.
1201 public void resetIndexingContext( Repository repository ) throws IndexUpdateFailedException
1203 if ( repository.hasIndex( ) && repository instanceof EditableRepository )
1205 EditableRepository eRepo = (EditableRepository) repository;
1206 ArchivaIndexingContext newCtx = getIndexManager( repository.getType( ) ).reset( repository.getIndexingContext( ) );
1207 eRepo.setIndexingContext( newCtx );
1213 * Creates a new repository instance with the same settings as this one. The cloned repository is not
1214 * registered or saved to the configuration.
1216 * @param repo The origin repository
1217 * @return The cloned repository.
1219 public ManagedRepository clone( ManagedRepository repo, String newId ) throws RepositoryException
1221 if (isRegisteredId( newId )) {
1222 throw new RepositoryException( "The new id exists already: " + newId );
1224 EditableManagedRepository newRepo = (EditableManagedRepository) managedRepositoryHandler.clone( repo, newId );
1229 public <T extends Repository> T clone( T repo, String newId ) throws RepositoryException
1231 if ( repo instanceof RemoteRepository )
1233 return (T) this.clone( (RemoteRepository) repo, newId );
1235 else if ( repo instanceof ManagedRepository )
1237 return (T) this.clone( (ManagedRepository) repo, newId );
1241 throw new RepositoryException( "This repository class is not supported " + repo.getClass( ).getName( ) );
1246 * Creates a new repository instance with the same settings as this one. The cloned repository is not
1247 * registered or saved to the configuration.
1249 * @param repo The origin repository
1250 * @return The cloned repository.
1252 public RemoteRepository clone( RemoteRepository repo, String newId ) throws RepositoryException
1254 if ( isRegisteredId( newId ) )
1256 throw new RepositoryException( "The given id exists already " + newId );
1258 RepositoryProvider provider = getProvider( repo.getType( ) );
1259 RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration( repo );
1261 RemoteRepository cloned = provider.createRemoteInstance( cfg );
1262 cloned.registerEventHandler( RepositoryEvent.ANY, this );
1267 public Repository getRepositoryOfAsset( StorageAsset asset )
1269 if ( asset instanceof Repository )
1271 return (Repository) asset;
1275 return getRepositories( ).stream( ).filter( r -> r.getRoot( )
1276 .getStorage( ).equals( asset.getStorage( ) ) ).findFirst( ).orElse( null );
1281 public <R extends Repository> ValidationResponse<R> validateRepository( R repository )
1283 Map<String, List<ValidationError>> errorMap = this.validators.stream( )
1284 .filter( ( validator ) -> validator.getType( ).equals( RepositoryType.ALL ) || repository.getType( ).equals( validator.getType( ) ) )
1285 .filter( val -> val.isFlavour( repository.getClass( ) ) )
1286 .flatMap( validator -> ( (RepositoryValidator<R>) validator ).apply( repository ).getResult( ).entrySet( ).stream( ) )
1287 .collect( Collectors.toMap(
1288 entry -> entry.getKey( ),
1289 entry -> entry.getValue( ),
1290 ( list1, list2 ) -> ListUtils.union( list1, list2 )
1292 return new ValidationResponse( repository, errorMap );
1296 public <R extends Repository> ValidationResponse<R> validateRepositoryForUpdate( R repository )
1298 Map<String, List<ValidationError>> errorMap = this.validators.stream( )
1299 .filter( ( validator ) -> validator.getType( ).equals( RepositoryType.ALL ) || repository.getType( ).equals( validator.getType( ) ) )
1300 .filter( val -> val.isFlavour( repository.getClass( ) ) )
1301 .flatMap( validator -> ( (RepositoryValidator<R>) validator ).applyForUpdate( repository ).getResult( ).entrySet( ).stream( ) )
1302 .collect( Collectors.toMap(
1303 entry -> entry.getKey( ),
1304 entry -> entry.getValue( ),
1305 ( list1, list2 ) -> ListUtils.union( list1, list2 )
1307 return new ValidationResponse( repository, errorMap );
1311 public void configurationEvent( ConfigurationEvent event )
1313 // We ignore the event, if the save was triggered by ourself
1314 if ( !ConfigurationHandler.REGISTRY_EVENT_TAG.equals( event.getTag( ) ) )
1322 public <T extends Event> void registerEventHandler( EventType<T> type, EventHandler<? super T> eventHandler )
1324 eventManager.registerEventHandler( type, eventHandler );
1329 public <T extends Event> void unregisterEventHandler( EventType<T> type, EventHandler<? super T> eventHandler )
1331 eventManager.unregisterEventHandler( type, eventHandler );
1336 public void handle( Event event )
1338 // To avoid event cycles:
1339 if ( sameOriginator( event ) )
1343 if ( event instanceof RepositoryIndexEvent )
1345 handleIndexCreationEvent( (RepositoryIndexEvent) event );
1347 // We propagate all events to our listeners, but with context of repository registry
1351 private void handleIndexCreationEvent( RepositoryIndexEvent event )
1353 if (!ignoreIndexing && !( event.getRepository() instanceof ManagedRepository ))
1355 RepositoryIndexEvent idxEvent = event;
1356 EditableRepository repo = (EditableRepository) idxEvent.getRepository( );
1359 ArchivaIndexManager idxmgr = getIndexManager( repo.getType( ) );
1360 if ( repo.getIndexingContext( ) != null )
1364 ArchivaIndexingContext newCtx = idxmgr.move( repo.getIndexingContext( ), repo );
1365 repo.setIndexingContext( newCtx );
1366 idxmgr.updateLocalIndexPath( repo );
1369 catch ( IndexCreationFailedException e )
1371 log.error( "Could not move index to new directory: '{}'", e.getMessage( ), e );
1378 ArchivaIndexingContext context = idxmgr.createContext( repo );
1379 repo.setIndexingContext( context );
1380 idxmgr.updateLocalIndexPath( repo );
1382 catch ( IndexCreationFailedException e )
1384 log.error( "Could not create index: '{}'", e.getMessage( ), e );
1391 private boolean sameOriginator( Event event )
1393 if ( event.getSource( ) == this )
1397 else if ( event.hasPreviousEvent( ) )
1399 return sameOriginator( event.getPreviousEvent( ) );
1407 private void pushEvent( Event event )
1409 eventManager.fireEvent( event );
1412 private <R extends Repository, C extends AbstractRepositoryConfiguration> void registerRepositoryHandler( RepositoryHandler<R, C> repositoryHandler )
1414 repositoryHandler.setRepositoryProviders( this.repositoryProviders );
1415 repositoryHandler.setRepositoryValidator( this.repositoryValidatorList );
1419 public void registerHandler( RepositoryHandler<?, ?> handler )
1421 if ( handler.getVariant( ).isAssignableFrom( RepositoryGroup.class ) )
1423 registerGroupHandler( (RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration>) handler );
1425 else if ( handler.getVariant( ).isAssignableFrom( ManagedRepository.class ) )
1427 registerManagedRepositoryHandler( (RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration>) handler );
1432 public boolean isRegisteredId( String id )
1434 return hasRepository( id );
1438 public <R extends Repository, C extends AbstractRepositoryConfiguration> RepositoryHandler<R, C> getHandler( Class<R> repositoryClazz, Class<C> configurationClazz )
1440 if ( repositoryClazz.isAssignableFrom( RepositoryGroup.class ) )
1442 return (RepositoryHandler<R, C>) this.groupHandler;
1444 else if ( repositoryClazz.isAssignableFrom( ManagedRepository.class ) )
1446 return (RepositoryHandler<R, C>) this.managedRepositoryHandler;
1454 public boolean isIgnoreIndexing( )
1456 return ignoreIndexing;
1459 public void setIgnoreIndexing( boolean ignoreIndexing )
1461 this.ignoreIndexing = ignoreIndexing;