]> source.dussan.org Git - archiva.git/blob
399c809e8249679b1ac8eda4563ad1624b65e24e
[archiva.git] /
1 package org.apache.archiva.repository.base;
2
3 /*
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
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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;
73
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;
84 import java.util.Map;
85 import java.util.Set;
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;
91
92 /**
93  * Registry for repositories. This is the central entry point for repositories. It provides methods for
94  * retrieving, adding and removing repositories.
95  * <p>
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.
98  * <p>
99  * TODO: Audit events
100  *
101  * @since 3.0
102  */
103 @Service( "repositoryRegistry" )
104 public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHandler<Event>,
105     RepositoryRegistry
106 {
107
108     private static final Logger log = LoggerFactory.getLogger( RepositoryRegistry.class );
109
110     /**
111      * We inject all repository providers
112      */
113     @Inject
114     List<RepositoryProvider> repositoryProviders;
115
116     @Inject
117     IndexManagerFactory indexManagerFactory;
118
119     @Inject
120     List<MetadataReader> metadataReaderList;
121
122     @Inject
123     List<RepositoryValidator<? extends Repository>> repositoryValidatorList;
124
125     @Inject
126     @Named( "repositoryContentFactory#default" )
127     RepositoryContentFactory repositoryContentFactory;
128
129
130     private boolean ignoreIndexing = false;
131
132     private final EventManager eventManager;
133
134
135     private Map<String, RemoteRepository> remoteRepositories = new HashMap<>( );
136     private Map<String, RemoteRepository> uRemoteRepositories = Collections.unmodifiableMap( remoteRepositories );
137
138     private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock( );
139
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;
144
145
146     private AtomicBoolean groups_initalized = new AtomicBoolean( false );
147     private AtomicBoolean managed_initialized = new AtomicBoolean( false );
148     private AtomicBoolean remote_initialized = new AtomicBoolean( false );
149
150
151     public ArchivaRepositoryRegistry( ConfigurationHandler configurationHandler, List<RepositoryValidator<? extends Repository>> validatorList )
152     {
153         this.eventManager = new EventManager( this );
154         this.configurationHandler = configurationHandler;
155         this.validators = initValidatorList( validatorList );
156     }
157
158
159     private Set<RepositoryValidator<? extends Repository>> initValidatorList( List<RepositoryValidator<? extends Repository>> validators )
160     {
161         TreeSet<RepositoryValidator<? extends Repository>> val = new TreeSet<>( );
162         for ( RepositoryValidator<? extends Repository> validator : validators )
163         {
164             val.add( validator );
165             validator.setRepositoryRegistry( this );
166         }
167         return val;
168     }
169
170     @Override
171     public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration )
172     {
173         this.configurationHandler.setArchivaConfiguration( archivaConfiguration );
174     }
175
176     @PostConstruct
177     private void initialize( )
178     {
179         rwLock.writeLock( ).lock( );
180         try
181         {
182             log.debug( "Initializing repository registry" );
183             initializeManagedRepositories();
184             updateRemoteRepositoriesFromConfig( );
185             pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.REMOTE_REPOS_INITIALIZED, this ) );
186             remote_initialized.set( true );
187
188             initializeRepositoryGroups( );
189
190             for ( RepositoryProvider provider : repositoryProviders )
191             {
192                 provider.addRepositoryEventHandler( this );
193             }
194             this.configurationHandler.addListener( this );
195         }
196         finally
197         {
198             rwLock.writeLock( ).unlock( );
199         }
200         pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.RELOADED, this ) );
201         if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
202         {
203             pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
204         }
205     }
206
207     private void initializeRepositoryGroups( )
208     {
209         if ( this.groupHandler != null )
210         {
211             this.groupHandler.initializeFromConfig( );
212             this.groups_initalized.set( true );
213             pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.GROUPS_INITIALIZED, this ) );
214         }
215     }
216
217     private void initializeManagedRepositories( )
218     {
219         if ( this.managedRepositoryHandler != null )
220         {
221             this.managedRepositoryHandler.initializeFromConfig( );
222             this.managed_initialized.set( true );
223             pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.MANAGED_REPOS_INITIALIZED, this ) );
224         }
225     }
226
227     public void registerGroupHandler( RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration> groupHandler )
228     {
229         this.groupHandler = groupHandler;
230         registerRepositoryHandler( groupHandler );
231         initializeRepositoryGroups( );
232         if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
233         {
234             pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
235         }
236     }
237
238     public void registerManagedRepositoryHandler( RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration> managedRepositoryHandler )
239     {
240         this.managedRepositoryHandler = managedRepositoryHandler;
241         registerRepositoryHandler( managedRepositoryHandler );
242         initializeManagedRepositories();
243         if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
244         {
245             pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
246         }
247     }
248
249
250     @PreDestroy
251     public void destroy( )
252     {
253         managedRepositoryHandler.close( );
254         for ( RemoteRepository repo : remoteRepositories.values( ) )
255         {
256             repo.close( );
257         }
258         remoteRepositories.clear( );
259         groupHandler.close( );
260         pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.DESTROYED, this ) );
261     }
262
263
264     public Map<RepositoryType, RepositoryProvider> getRepositoryProviderMap( )
265     {
266         Map<RepositoryType, RepositoryProvider> map = new HashMap<>( );
267         if ( repositoryProviders != null )
268         {
269             for ( RepositoryProvider provider : repositoryProviders )
270             {
271                 for ( RepositoryType type : provider.provides( ) )
272                 {
273                     map.put( type, provider );
274                 }
275             }
276         }
277         return map;
278     }
279
280     public RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
281     {
282         return repositoryProviders.stream( ).filter( repositoryProvider -> repositoryProvider.provides( ).contains( type ) ).findFirst( ).orElseThrow( ( ) -> new RepositoryException( "Repository type cannot be handled: " + type ) );
283     }
284
285     /*
286      * Updates the repositories
287      */
288     private void updateManagedRepositoriesFromConfig( )
289     {
290         managedRepositoryHandler.initializeFromConfig( );
291     }
292
293
294     private String getStagingId( String repoId )
295     {
296         return repoId + StagingRepositoryFeature.STAGING_REPO_POSTFIX;
297     }
298
299
300     @Override
301     public ArchivaIndexManager getIndexManager( RepositoryType type )
302     {
303         return indexManagerFactory.getIndexManager( type );
304     }
305
306     @Override
307     public MetadataReader getMetadataReader( final RepositoryType type ) throws UnsupportedRepositoryTypeException
308     {
309         if ( metadataReaderList != null )
310         {
311             return metadataReaderList.stream( ).filter( mr -> mr.isValidForType( type ) ).findFirst( ).orElseThrow( ( ) -> new UnsupportedRepositoryTypeException( type ) );
312         }
313         else
314         {
315             throw new UnsupportedRepositoryTypeException( type );
316         }
317     }
318
319     private void createIndexingContext( EditableRepository editableRepo ) throws RepositoryException
320     {
321         if ( editableRepo.supportsFeature( IndexCreationFeature.class ) )
322         {
323             ArchivaIndexManager idxManager = getIndexManager( editableRepo.getType( ) );
324             try
325             {
326                 editableRepo.setIndexingContext( idxManager.createContext( editableRepo ) );
327                 idxManager.updateLocalIndexPath( editableRepo );
328             }
329             catch ( IndexCreationFailedException e )
330             {
331                 throw new RepositoryException( "Could not create index for repository " + editableRepo.getId( ) + ": " + e.getMessage( ), e );
332             }
333         }
334     }
335
336
337     private void updateRemoteRepositoriesFromConfig( )
338     {
339         try
340         {
341             List<RemoteRepositoryConfiguration> remoteRepoConfigs =
342                 configurationHandler.getBaseConfiguration( ).getRemoteRepositories( );
343
344             if ( remoteRepoConfigs == null )
345             {
346                 return;
347             }
348             Set<String> repoIds = new HashSet<>( );
349             for ( RemoteRepositoryConfiguration repoConfig : remoteRepoConfigs )
350             {
351                 putRepository( repoConfig, null );
352                 repoIds.add( repoConfig.getId( ) );
353             }
354
355             List<String> toRemove = remoteRepositories.keySet( ).stream( ).filter( id -> !repoIds.contains( id ) ).collect( Collectors.toList( ) );
356             for ( String id : toRemove )
357             {
358                 RemoteRepository removed = remoteRepositories.remove( id );
359                 removed.close( );
360             }
361
362         }
363         catch ( Throwable e )
364         {
365             log.error( "Could not initialize remote repositories from config: {}", e.getMessage( ), e );
366             return;
367         }
368     }
369
370     private RemoteRepository createNewRemoteRepository( RepositoryProvider provider, RemoteRepositoryConfiguration cfg ) throws RepositoryException
371     {
372         log.debug( "Creating remote repo {}", cfg.getId( ) );
373         RemoteRepository repo = provider.createRemoteInstance( cfg );
374         updateRepositoryReferences( provider, repo, cfg, null );
375         return repo;
376
377     }
378
379     private void updateRepositoryReferences( RepositoryProvider provider, RemoteRepository repo, RemoteRepositoryConfiguration cfg, Configuration configuration ) throws RepositoryException
380     {
381         if ( repo instanceof EditableRemoteRepository && repo.getContent( ) == null )
382         {
383             EditableRemoteRepository editableRepo = (EditableRemoteRepository) repo;
384             editableRepo.setContent( repositoryContentFactory.getRemoteRepositoryContent( repo ) );
385             if ( repo.supportsFeature( IndexCreationFeature.class ) && repo.getIndexingContext( ) == null )
386             {
387                 createIndexingContext( editableRepo );
388             }
389         }
390         repo.registerEventHandler( RepositoryEvent.ANY, this );
391     }
392
393
394     /**
395      * Returns all repositories that are registered. There is no defined order of the returned repositories.
396      *
397      * @return a list of managed and remote repositories
398      */
399     @Override
400     public Collection<Repository> getRepositories( )
401     {
402         rwLock.readLock( ).lock( );
403         try
404         {
405             return Stream.concat( managedRepositoryHandler.getAll().stream( ), remoteRepositories.values( ).stream( ) ).collect( Collectors.toList( ) );
406         }
407         finally
408         {
409             rwLock.readLock( ).unlock( );
410         }
411     }
412
413     /**
414      * Returns only the managed repositories. There is no defined order of the returned repositories.
415      *
416      * @return a list of managed repositories
417      */
418     @Override
419     public Collection<ManagedRepository> getManagedRepositories( )
420     {
421         rwLock.readLock( ).lock( );
422         try
423         {
424             return managed_initialized.get() ? managedRepositoryHandler.getAll( ) : Collections.emptyList();
425         }
426         finally
427         {
428             rwLock.readLock( ).unlock( );
429         }
430     }
431
432     /**
433      * Returns only the remote repositories. There is no defined order of the returned repositories.
434      *
435      * @return a list of remote repositories
436      */
437     @Override
438     public Collection<RemoteRepository> getRemoteRepositories( )
439     {
440         rwLock.readLock( ).lock( );
441         try
442         {
443             return uRemoteRepositories.values( );
444         }
445         finally
446         {
447             rwLock.readLock( ).unlock( );
448         }
449     }
450
451     @Override
452     public Collection<RepositoryGroup> getRepositoryGroups( )
453     {
454         rwLock.readLock( ).lock( );
455         try
456         {
457             return groupHandler.getAll( );
458         }
459         finally
460         {
461             rwLock.readLock( ).unlock( );
462         }
463     }
464
465     /**
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.
468      *
469      * @param repoId the repository id
470      * @return the repository if found, otherwise null
471      */
472     @Override
473     public Repository getRepository( String repoId )
474     {
475         rwLock.readLock( ).lock( );
476         try
477         {
478             log.debug( "getRepository {}", repoId );
479             if ( managedRepositoryHandler.hasRepository( repoId ) )
480             {
481                 log.debug( "Managed repo" );
482                 return managedRepositoryHandler.get( repoId );
483             }
484             else if ( remoteRepositories.containsKey( repoId ) )
485             {
486                 log.debug( "Remote repo" );
487                 return remoteRepositories.get( repoId );
488             }
489             else if ( groupHandler.hasRepository( repoId ) )
490             {
491                 return groupHandler.get( repoId );
492             }
493             else
494             {
495                 return null;
496             }
497         }
498         finally
499         {
500             rwLock.readLock( ).unlock( );
501         }
502     }
503
504     /**
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.
507      *
508      * @param repoId the repository id
509      * @return the managed repository if found, otherwise null
510      */
511     @Override
512     public ManagedRepository getManagedRepository( String repoId )
513     {
514         rwLock.readLock( ).lock( );
515         try
516         {
517             return managed_initialized.get() ? managedRepositoryHandler.get( repoId ) : null;
518         }
519         finally
520         {
521             rwLock.readLock( ).unlock( );
522         }
523     }
524
525     /**
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.
528      *
529      * @param repoId the repository id
530      * @return the remote repository if found, otherwise null
531      */
532     @Override
533     public RemoteRepository getRemoteRepository( String repoId )
534     {
535         rwLock.readLock( ).lock( );
536         try
537         {
538             return remoteRepositories.get( repoId );
539         }
540         finally
541         {
542             rwLock.readLock( ).unlock( );
543         }
544     }
545
546     @Override
547     public RepositoryGroup getRepositoryGroup( String groupId )
548     {
549         rwLock.readLock( ).lock( );
550         try
551         {
552             return groupHandler.get( groupId );
553         }
554         finally
555         {
556             rwLock.readLock( ).unlock( );
557         }
558     }
559
560     @Override
561     public boolean hasRepository( String repoId )
562     {
563         return ( managedRepositoryHandler != null && managedRepositoryHandler.hasRepository( repoId ) )
564             || ( this.remoteRepositories != null && this.remoteRepositories.containsKey( repoId ) )
565             || ( this.groupHandler != null && groupHandler.hasRepository( repoId ) );
566     }
567
568     @Override
569     public boolean hasManagedRepository( String repoId )
570     {
571         return managedRepositoryHandler.hasRepository( repoId );
572     }
573
574     @Override
575     public boolean hasRemoteRepository( String repoId )
576     {
577         return this.remoteRepositories.containsKey( repoId );
578     }
579
580     @Override
581     public boolean hasRepositoryGroup( String groupId )
582     {
583         return this.groupHandler != null && groupHandler.hasRepository( groupId );
584     }
585
586     protected void saveConfiguration( Configuration configuration ) throws IndeterminateConfigurationException, RegistryException
587     {
588         configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
589     }
590
591     /**
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.
595      *
596      * @param managedRepository the new repository.
597      * @throws RepositoryException if the new repository could not be saved to the configuration.
598      */
599     @Override
600     public ManagedRepository putRepository( ManagedRepository managedRepository ) throws RepositoryException
601     {
602         rwLock.writeLock( ).lock( );
603         try
604         {
605             return managed_initialized.get() ? managedRepositoryHandler.put( managedRepository ) : null;
606         }
607         finally
608         {
609             rwLock.writeLock( ).unlock( );
610         }
611     }
612
613     /**
614      * Adds a new repository or updates the repository with the same id, if it exists already.
615      * The configuration is saved immediately.
616      *
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.
620      */
621     @Override
622     public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration ) throws RepositoryException
623     {
624         rwLock.writeLock( ).lock( );
625         try
626         {
627             return managedRepositoryHandler.put( managedRepositoryConfiguration );
628         }
629         finally
630         {
631             rwLock.writeLock( ).unlock( );
632         }
633
634     }
635
636     /**
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.
639      *
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
644      */
645     @Override
646     public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration ) throws RepositoryException
647     {
648         rwLock.writeLock( ).lock( );
649         try
650         {
651             return managedRepositoryHandler.put( managedRepositoryConfiguration, configuration );
652         }
653         finally
654         {
655             rwLock.writeLock( ).unlock( );
656         }
657     }
658
659
660     /**
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.
664      *
665      * @param repositoryGroup the new repository group.
666      * @throws RepositoryException if the new repository group could not be saved to the configuration.
667      */
668     @Override
669     public RepositoryGroup putRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
670     {
671         rwLock.writeLock( ).lock( );
672         try
673         {
674             if ( this.groupHandler == null )
675             {
676                 throw new RepositoryException( "Fatal error. RepositoryGroupHandler not registered!" );
677             }
678             return this.groupHandler.put( repositoryGroup );
679         }
680         finally
681         {
682             rwLock.writeLock( ).unlock( );
683         }
684     }
685
686     /**
687      * Adds a new repository group or updates the repository with the same id, if it exists already.
688      * The configuration is saved immediately.
689      *
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.
693      */
694     @Override
695     public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException
696     {
697         rwLock.writeLock( ).lock( );
698         try
699         {
700             return groupHandler.put( repositoryGroupConfiguration );
701         }
702         finally
703         {
704             rwLock.writeLock( ).unlock( );
705         }
706
707     }
708
709     @Override
710     public CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> putRepositoryGroupAndValidate( RepositoryGroupConfiguration repositoryGroupConfiguration )
711         throws RepositoryException
712     {
713         rwLock.writeLock( ).lock( );
714         try
715         {
716             return groupHandler.putWithCheck( repositoryGroupConfiguration, groupHandler.getValidator( ) );
717         }
718         finally
719         {
720             rwLock.writeLock( ).unlock( );
721         }
722     }
723
724     /**
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.
727      *
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
732      */
733     @Override
734     public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException
735     {
736         rwLock.writeLock( ).lock( );
737         try
738         {
739             return groupHandler.put( repositoryGroupConfiguration, configuration );
740         }
741         finally
742         {
743             rwLock.writeLock( ).unlock( );
744         }
745     }
746
747     private void replaceOrAddRepositoryConfig( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration )
748     {
749         if ( configuration != null )
750         {
751             RemoteRepositoryConfiguration oldCfg = configuration.findRemoteRepositoryById( remoteRepositoryConfiguration.getId( ) );
752             if ( oldCfg != null )
753             {
754                 configuration.removeRemoteRepository( oldCfg );
755             }
756             configuration.addRemoteRepository( remoteRepositoryConfiguration );
757         }
758     }
759
760     @Override
761     public RemoteRepository putRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException
762     {
763         rwLock.writeLock( ).lock( );
764         try
765         {
766             final String id = remoteRepository.getId( );
767             if ( managedRepositoryHandler.hasRepository( id ) )
768             {
769                 throw new RepositoryException( "There exists a managed repository with id " + id + ". Could not update with remote repository." );
770             }
771             RemoteRepository originRepo = remoteRepositories.put( id, remoteRepository );
772             RemoteRepositoryConfiguration oldCfg = null;
773             RemoteRepositoryConfiguration newCfg;
774             try
775             {
776                 if ( originRepo != null && originRepo != remoteRepository )
777                 {
778                     originRepo.close( );
779                 }
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 )
785                 {
786                     configuration.removeRemoteRepository( oldCfg );
787                 }
788                 configuration.addRemoteRepository( newCfg );
789                 if ( remoteRepository != originRepo )
790                 {
791                     pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, remoteRepository ) );
792                 }
793                 else
794                 {
795                     pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, remoteRepository ) );
796                 }
797                 return remoteRepository;
798             }
799             catch ( Exception e )
800             {
801                 // Rollback
802                 if ( originRepo != null )
803                 {
804                     remoteRepositories.put( id, originRepo );
805                 }
806                 else
807                 {
808                     remoteRepositories.remove( id );
809                 }
810                 if ( oldCfg != null )
811                 {
812                     RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( id );
813                     if ( cfg != null )
814                     {
815                         configuration.removeRemoteRepository( cfg );
816                         configuration.addRemoteRepository( oldCfg );
817                     }
818                 }
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( ) ) );
821             }
822         }
823         finally
824         {
825             rwLock.writeLock( ).unlock( );
826         }
827     }
828
829     /**
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.
832      *
833      * @param remoteRepository the remote repository to add
834      * @throws RepositoryException if an error occurs during configuration save
835      */
836     @Override
837     public RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException
838     {
839         rwLock.writeLock( ).lock( );
840         try
841         {
842             Configuration configuration = configurationHandler.getBaseConfiguration( );
843             try
844             {
845                 RemoteRepository repo = putRepository( remoteRepository, configuration );
846                 saveConfiguration( configuration );
847                 return repo;
848             }
849             catch ( RegistryException | IndeterminateConfigurationException e )
850             {
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( ) ) );
853             }
854         }
855         finally
856         {
857             rwLock.writeLock( ).unlock( );
858         }
859     }
860
861     /**
862      * Adds a new repository or updates the repository with the same id, if it exists already.
863      * The configuration is saved immediately.
864      *
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.
868      */
869     @Override
870     public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration ) throws RepositoryException
871     {
872         rwLock.writeLock( ).lock( );
873         try
874         {
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 );
881             try
882             {
883                 saveConfiguration( configuration );
884             }
885             catch ( IndeterminateConfigurationException | RegistryException e )
886             {
887                 if ( oldCfg != null )
888                 {
889                     getProvider( repositoryType ).updateRemoteInstance( (EditableRemoteRepository) repo, oldCfg );
890                 }
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( ) );
893             }
894             return repo;
895         }
896         finally
897         {
898             rwLock.writeLock( ).unlock( );
899         }
900
901     }
902
903     /**
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.
906      *
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
911      */
912     @Override
913     @SuppressWarnings( "unchecked" )
914     public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration ) throws RepositoryException
915     {
916         rwLock.writeLock( ).lock( );
917         try
918         {
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( ) )
925             {
926                 if ( repo instanceof EditableRemoteRepository )
927                 {
928                     getProvider( repoType ).updateRemoteInstance( (EditableRemoteRepository) repo, remoteRepositoryConfiguration );
929                 }
930                 else
931                 {
932                     throw new RepositoryException( "The repository is not editable " + id );
933                 }
934             }
935             else
936             {
937                 repo = getProvider( repoType ).createRemoteInstance( remoteRepositoryConfiguration );
938                 remoteRepositories.put( id, repo );
939                 registeredNew = true;
940             }
941             updateRepositoryReferences( getProvider( repoType ), repo, remoteRepositoryConfiguration, configuration );
942             replaceOrAddRepositoryConfig( remoteRepositoryConfiguration, configuration );
943             if ( registeredNew )
944             {
945                 pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, repo ) );
946             }
947             else
948             {
949                 pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, repo ) );
950             }
951             return repo;
952         }
953         finally
954         {
955             rwLock.writeLock( ).unlock( );
956         }
957
958
959     }
960
961     @Override
962     public void removeRepository( String repoId ) throws RepositoryException
963     {
964         Repository repo = getRepository( repoId );
965         if ( repo != null )
966         {
967             removeRepository( repo );
968         }
969     }
970
971     @Override
972     public void removeRepository( Repository repo ) throws RepositoryException
973     {
974         if ( repo == null )
975         {
976             log.warn( "Trying to remove null repository" );
977             return;
978         }
979         if ( repo instanceof RemoteRepository )
980         {
981             removeRepository( (RemoteRepository) repo );
982         }
983         else if ( repo instanceof ManagedRepository )
984         {
985             removeRepository( (ManagedRepository) repo );
986         }
987         else if ( repo instanceof RepositoryGroup )
988         {
989             removeRepositoryGroup( (RepositoryGroup) repo );
990         }
991         else
992         {
993             throw new RepositoryException( "Repository type not known: " + repo.getClass( ) );
994         }
995     }
996
997     /**
998      * Removes a managed repository from the registry and configuration, if it exists.
999      * The change is saved to the configuration immediately.
1000      *
1001      * @param managedRepository the managed repository to remove
1002      * @throws RepositoryException if a error occurs during configuration save
1003      */
1004     @Override
1005     public void removeRepository( ManagedRepository managedRepository ) throws RepositoryException
1006     {
1007         if ( managedRepository == null )
1008         {
1009             return;
1010         }
1011         rwLock.writeLock( ).lock( );
1012         try
1013         {
1014             if (managed_initialized.get() ) managedRepositoryHandler.remove( managedRepository.getId( ) );
1015         }
1016         finally
1017         {
1018             rwLock.writeLock( ).unlock( );
1019         }
1020     }
1021
1022
1023     @Override
1024     public void removeRepository( ManagedRepository managedRepository, Configuration configuration ) throws RepositoryException
1025     {
1026         if ( managedRepository == null )
1027         {
1028             return;
1029         }
1030             rwLock.writeLock( ).lock( );
1031             try
1032             {
1033                 if (managed_initialized.get()) managedRepositoryHandler.remove( managedRepository.getId( ), configuration );
1034             }
1035             finally
1036             {
1037                 rwLock.writeLock( ).unlock( );
1038             }
1039
1040     }
1041
1042
1043     /**
1044      * Removes a repository group from the registry and configuration, if it exists.
1045      * The change is saved to the configuration immediately.
1046      *
1047      * @param repositoryGroup the repository group to remove
1048      * @throws RepositoryException if a error occurs during configuration save
1049      */
1050     @Override
1051     public void removeRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
1052     {
1053         if ( repositoryGroup == null )
1054         {
1055             return;
1056         }
1057         final String id = repositoryGroup.getId( );
1058         if ( groupHandler.hasRepository( id ) )
1059         {
1060             rwLock.writeLock( ).lock( );
1061             try
1062             {
1063                 groupHandler.remove( id );
1064             }
1065             finally
1066             {
1067                 rwLock.writeLock( ).unlock( );
1068             }
1069         }
1070     }
1071
1072     @Override
1073     public void removeRepositoryGroup( RepositoryGroup repositoryGroup, Configuration configuration ) throws RepositoryException
1074     {
1075         if ( repositoryGroup == null )
1076         {
1077             return;
1078         }
1079         final String id = repositoryGroup.getId( );
1080         if ( groupHandler.hasRepository( id ) )
1081         {
1082             rwLock.writeLock( ).lock( );
1083             try
1084             {
1085                 groupHandler.remove( id, configuration );
1086             }
1087             finally
1088             {
1089                 rwLock.writeLock( ).unlock( );
1090             }
1091         }
1092     }
1093
1094     private void doRemoveRepo( RemoteRepository repo, Configuration configuration )
1095     {
1096         repo.close( );
1097         RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( repo.getId( ) );
1098         if ( cfg != null )
1099         {
1100             configuration.removeRemoteRepository( cfg );
1101         }
1102         List<ProxyConnectorConfiguration> proxyConnectors = new ArrayList<>( configuration.getProxyConnectors( ) );
1103         for ( ProxyConnectorConfiguration proxyConnector : proxyConnectors )
1104         {
1105             if ( StringUtils.equals( proxyConnector.getTargetRepoId( ), repo.getId( ) ) )
1106             {
1107                 configuration.removeProxyConnector( proxyConnector );
1108             }
1109         }
1110     }
1111
1112     /**
1113      * Removes the remote repository from the registry and configuration.
1114      * The change is saved to the configuration immediately.
1115      *
1116      * @param remoteRepository the remote repository to remove
1117      * @throws RepositoryException if a error occurs during configuration save
1118      */
1119     @Override
1120     public void removeRepository( RemoteRepository remoteRepository ) throws RepositoryException
1121     {
1122         if ( remoteRepository == null )
1123         {
1124             return;
1125         }
1126         final String id = remoteRepository.getId( );
1127         RemoteRepository repo = getRemoteRepository( id );
1128         if ( repo != null )
1129         {
1130             rwLock.writeLock( ).lock( );
1131             try
1132             {
1133                 repo = remoteRepositories.remove( id );
1134                 if ( repo != null )
1135                 {
1136                     Configuration configuration = configurationHandler.getBaseConfiguration( );
1137                     doRemoveRepo( repo, configuration );
1138                     saveConfiguration( configuration );
1139                 }
1140                 pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
1141             }
1142             catch ( RegistryException | IndeterminateConfigurationException e )
1143             {
1144                 // Rollback
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( ) );
1148             }
1149             finally
1150             {
1151                 rwLock.writeLock( ).unlock( );
1152             }
1153         }
1154     }
1155
1156     @Override
1157     public void removeRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException
1158     {
1159         if ( remoteRepository == null )
1160         {
1161             return;
1162         }
1163         final String id = remoteRepository.getId( );
1164         RemoteRepository repo = getRemoteRepository( id );
1165         if ( repo != null )
1166         {
1167             rwLock.writeLock( ).lock( );
1168             try
1169             {
1170                 repo = remoteRepositories.remove( id );
1171                 if ( repo != null )
1172                 {
1173                     doRemoveRepo( repo, configuration );
1174                 }
1175                 pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
1176             }
1177             finally
1178             {
1179                 rwLock.writeLock( ).unlock( );
1180             }
1181         }
1182
1183     }
1184
1185     /**
1186      * Reloads the registry from the configuration.
1187      */
1188     @Override
1189     public void reload( )
1190     {
1191         initialize( );
1192     }
1193
1194     /**
1195      * Resets the indexing context of a given repository.
1196      *
1197      * @param repository The repository
1198      * @throws IndexUpdateFailedException If the index could not be resetted.
1199      */
1200     @Override
1201     public void resetIndexingContext( Repository repository ) throws IndexUpdateFailedException
1202     {
1203         if ( repository.hasIndex( ) && repository instanceof EditableRepository )
1204         {
1205             EditableRepository eRepo = (EditableRepository) repository;
1206             ArchivaIndexingContext newCtx = getIndexManager( repository.getType( ) ).reset( repository.getIndexingContext( ) );
1207             eRepo.setIndexingContext( newCtx );
1208         }
1209     }
1210
1211
1212     /**
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.
1215      *
1216      * @param repo The origin repository
1217      * @return The cloned repository.
1218      */
1219     public ManagedRepository clone( ManagedRepository repo, String newId ) throws RepositoryException
1220     {
1221         if (isRegisteredId( newId )) {
1222             throw new RepositoryException( "The new id exists already: " + newId );
1223         }
1224         EditableManagedRepository newRepo = (EditableManagedRepository) managedRepositoryHandler.clone( repo, newId );
1225         return newRepo;
1226     }
1227
1228     @Override
1229     public <T extends Repository> T clone( T repo, String newId ) throws RepositoryException
1230     {
1231         if ( repo instanceof RemoteRepository )
1232         {
1233             return (T) this.clone( (RemoteRepository) repo, newId );
1234         }
1235         else if ( repo instanceof ManagedRepository )
1236         {
1237             return (T) this.clone( (ManagedRepository) repo, newId );
1238         }
1239         else
1240         {
1241             throw new RepositoryException( "This repository class is not supported " + repo.getClass( ).getName( ) );
1242         }
1243     }
1244
1245     /**
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.
1248      *
1249      * @param repo The origin repository
1250      * @return The cloned repository.
1251      */
1252     public RemoteRepository clone( RemoteRepository repo, String newId ) throws RepositoryException
1253     {
1254         if ( isRegisteredId( newId ) )
1255         {
1256             throw new RepositoryException( "The given id exists already " + newId );
1257         }
1258         RepositoryProvider provider = getProvider( repo.getType( ) );
1259         RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration( repo );
1260         cfg.setId( newId );
1261         RemoteRepository cloned = provider.createRemoteInstance( cfg );
1262         cloned.registerEventHandler( RepositoryEvent.ANY, this );
1263         return cloned;
1264     }
1265
1266     @Override
1267     public Repository getRepositoryOfAsset( StorageAsset asset )
1268     {
1269         if ( asset instanceof Repository )
1270         {
1271             return (Repository) asset;
1272         }
1273         else
1274         {
1275             return getRepositories( ).stream( ).filter( r -> r.getRoot( )
1276                 .getStorage( ).equals( asset.getStorage( ) ) ).findFirst( ).orElse( null );
1277         }
1278     }
1279
1280     @Override
1281     public <R extends Repository> ValidationResponse<R> validateRepository( R repository )
1282     {
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 )
1291             ) );
1292         return new ValidationResponse( repository, errorMap );
1293     }
1294
1295     @Override
1296     public <R extends Repository> ValidationResponse<R> validateRepositoryForUpdate( R repository )
1297     {
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 )
1306             ) );
1307         return new ValidationResponse( repository, errorMap );
1308     }
1309
1310     @Override
1311     public void configurationEvent( ConfigurationEvent event )
1312     {
1313         // We ignore the event, if the save was triggered by ourself
1314         if ( !ConfigurationHandler.REGISTRY_EVENT_TAG.equals( event.getTag( ) ) )
1315         {
1316             reload( );
1317         }
1318     }
1319
1320
1321     @Override
1322     public <T extends Event> void registerEventHandler( EventType<T> type, EventHandler<? super T> eventHandler )
1323     {
1324         eventManager.registerEventHandler( type, eventHandler );
1325     }
1326
1327
1328     @Override
1329     public <T extends Event> void unregisterEventHandler( EventType<T> type, EventHandler<? super T> eventHandler )
1330     {
1331         eventManager.unregisterEventHandler( type, eventHandler );
1332     }
1333
1334
1335     @Override
1336     public void handle( Event event )
1337     {
1338         // To avoid event cycles:
1339         if ( sameOriginator( event ) )
1340         {
1341             return;
1342         }
1343         if ( event instanceof RepositoryIndexEvent )
1344         {
1345             handleIndexCreationEvent( (RepositoryIndexEvent) event );
1346         }
1347         // We propagate all events to our listeners, but with context of repository registry
1348         pushEvent( event );
1349     }
1350
1351     private void handleIndexCreationEvent( RepositoryIndexEvent event )
1352     {
1353         if (!ignoreIndexing && !( event.getRepository() instanceof  ManagedRepository ))
1354         {
1355             RepositoryIndexEvent idxEvent = event;
1356             EditableRepository repo = (EditableRepository) idxEvent.getRepository( );
1357             if ( repo != null )
1358             {
1359                 ArchivaIndexManager idxmgr = getIndexManager( repo.getType( ) );
1360                 if ( repo.getIndexingContext( ) != null )
1361                 {
1362                     try
1363                     {
1364                         ArchivaIndexingContext newCtx = idxmgr.move( repo.getIndexingContext( ), repo );
1365                         repo.setIndexingContext( newCtx );
1366                         idxmgr.updateLocalIndexPath( repo );
1367
1368                     }
1369                     catch ( IndexCreationFailedException e )
1370                     {
1371                         log.error( "Could not move index to new directory: '{}'", e.getMessage( ), e );
1372                     }
1373                 }
1374                 else
1375                 {
1376                     try
1377                     {
1378                         ArchivaIndexingContext context = idxmgr.createContext( repo );
1379                         repo.setIndexingContext( context );
1380                         idxmgr.updateLocalIndexPath( repo );
1381                     }
1382                     catch ( IndexCreationFailedException e )
1383                     {
1384                         log.error( "Could not create index:  '{}'", e.getMessage( ), e );
1385                     }
1386                 }
1387             }
1388         }
1389     }
1390
1391     private boolean sameOriginator( Event event )
1392     {
1393         if ( event.getSource( ) == this )
1394         {
1395             return true;
1396         }
1397         else if ( event.hasPreviousEvent( ) )
1398         {
1399             return sameOriginator( event.getPreviousEvent( ) );
1400         }
1401         else
1402         {
1403             return false;
1404         }
1405     }
1406
1407     private void pushEvent( Event event )
1408     {
1409         eventManager.fireEvent( event );
1410     }
1411
1412     private <R extends Repository, C extends AbstractRepositoryConfiguration> void registerRepositoryHandler( RepositoryHandler<R, C> repositoryHandler )
1413     {
1414         repositoryHandler.setRepositoryProviders( this.repositoryProviders );
1415         repositoryHandler.setRepositoryValidator( this.repositoryValidatorList );
1416     }
1417
1418     @Override
1419     public void registerHandler( RepositoryHandler<?, ?> handler )
1420     {
1421         if ( handler.getVariant( ).isAssignableFrom( RepositoryGroup.class ) )
1422         {
1423             registerGroupHandler( (RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration>) handler );
1424         }
1425         else if ( handler.getVariant( ).isAssignableFrom( ManagedRepository.class ) )
1426         {
1427             registerManagedRepositoryHandler( (RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration>) handler );
1428         }
1429     }
1430
1431     @Override
1432     public boolean isRegisteredId( String id )
1433     {
1434         return hasRepository( id );
1435     }
1436
1437     @Override
1438     public <R extends Repository, C extends AbstractRepositoryConfiguration> RepositoryHandler<R, C> getHandler( Class<R> repositoryClazz, Class<C> configurationClazz )
1439     {
1440         if ( repositoryClazz.isAssignableFrom( RepositoryGroup.class ) )
1441         {
1442             return (RepositoryHandler<R, C>) this.groupHandler;
1443         }
1444         else if ( repositoryClazz.isAssignableFrom( ManagedRepository.class ) )
1445         {
1446             return (RepositoryHandler<R, C>) this.managedRepositoryHandler;
1447         }
1448         else
1449         {
1450             return null;
1451         }
1452     }
1453
1454     public boolean isIgnoreIndexing( )
1455     {
1456         return ignoreIndexing;
1457     }
1458
1459     public void setIgnoreIndexing( boolean ignoreIndexing )
1460     {
1461         this.ignoreIndexing = ignoreIndexing;
1462     }
1463
1464
1465 }