]> source.dussan.org Git - archiva.git/blob
385cd16a6495d4e8b7965399cd6e3bb0ee508f3c
[archiva.git] /
1 package org.apache.archiva.repository;
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.configuration.ArchivaConfiguration;
23 import org.apache.archiva.configuration.Configuration;
24 import org.apache.archiva.configuration.ConfigurationEvent;
25 import org.apache.archiva.configuration.ConfigurationListener;
26 import org.apache.archiva.configuration.IndeterminateConfigurationException;
27 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
28 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
29 import org.apache.archiva.redback.components.registry.RegistryException;
30 import org.apache.archiva.repository.features.ArtifactCleanupFeature;
31 import org.apache.archiva.repository.features.StagingRepositoryFeature;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34 import org.springframework.stereotype.Service;
35
36 import javax.annotation.PostConstruct;
37 import javax.inject.Inject;
38 import javax.inject.Named;
39 import java.util.Collection;
40 import java.util.Collections;
41 import java.util.HashMap;
42 import java.util.LinkedHashMap;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.concurrent.locks.ReentrantReadWriteLock;
46 import java.util.stream.Collectors;
47 import java.util.stream.Stream;
48
49 /**
50  * Registry for repositories. This is the central entry point for repositories. It provides methods for
51  * retrieving, adding and removing repositories.
52  *
53  * The modification methods addXX and removeXX persist the changes immediately to the configuration. If the
54  * configuration save fails the changes are rolled back.
55  *
56  * TODO: Audit events should be sent, but we don't want dependency to the repsitory-metadata-api
57  */
58 @Service( "repositoryRegistry" )
59 public class RepositoryRegistry implements ConfigurationListener {
60
61     private static final Logger log = LoggerFactory.getLogger( RepositoryRegistry.class );
62
63     /**
64      * We inject all repository providers
65      */
66     @Inject
67     List<RepositoryProvider> repositoryProviders;
68
69     @Inject
70     ArchivaConfiguration archivaConfiguration;
71
72     @Inject
73     @Named("repositoryContentFactory#default")
74     RepositoryContentFactory repositoryContentFactory;
75
76
77
78     private Map<String, ManagedRepository> managedRepositories = new HashMap<>( );
79     private Map<String, ManagedRepository> uManagedRepository = Collections.unmodifiableMap( managedRepositories );
80
81     private Map<String, RemoteRepository> remoteRepositories = new HashMap<>( );
82     private Map<String, RemoteRepository> uRemoteRepositories = Collections.unmodifiableMap( remoteRepositories );
83
84     private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock( );
85
86     public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration) {
87         this.archivaConfiguration = archivaConfiguration;
88     }
89
90     @PostConstruct
91     private void initialize( )
92     {
93         rwLock.writeLock( ).lock( );
94         try
95         {
96             managedRepositories.clear( );
97             managedRepositories.putAll( getManagedRepositoriesFromConfig( ) );
98             remoteRepositories.clear( );
99             remoteRepositories.putAll( getRemoteRepositoriesFromConfig( ) );
100             // archivaConfiguration.addChangeListener(this);
101             archivaConfiguration.addListener(this);
102         }
103         finally
104         {
105             rwLock.writeLock( ).unlock( );
106         }
107     }
108
109     private Map<RepositoryType, RepositoryProvider> createProviderMap( )
110     {
111         Map<RepositoryType, RepositoryProvider> map = new HashMap<>( );
112         if ( repositoryProviders != null )
113         {
114             for ( RepositoryProvider provider : repositoryProviders )
115             {
116                 for ( RepositoryType type : provider.provides( ) )
117                 {
118                     map.put( type, provider );
119                 }
120             }
121         }
122         return map;
123     }
124
125     private RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
126     {
127         return repositoryProviders.stream( ).filter( repositoryProvider -> repositoryProvider.provides( ).contains( type ) ).findFirst( ).orElseThrow( ( ) -> new RepositoryException( "Repository type cannot be handled: " + type ) );
128     }
129
130     private Map<String, ManagedRepository> getManagedRepositoriesFromConfig( )
131     {
132         try
133         {
134             List<ManagedRepositoryConfiguration> managedRepoConfigs =
135                 getArchivaConfiguration( ).getConfiguration( ).getManagedRepositories( );
136
137             if ( managedRepoConfigs == null )
138             {
139                 return Collections.EMPTY_MAP;
140             }
141
142             Map<String, ManagedRepository> managedRepos = new LinkedHashMap<>( managedRepoConfigs.size( ) );
143
144             Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap( );
145             for ( ManagedRepositoryConfiguration repoConfig : managedRepoConfigs )
146             {
147                 RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
148                 if ( providerMap.containsKey( repositoryType ) )
149                 {
150                     try
151                     {
152                         ManagedRepository repo = createNewManagedRepository( providerMap.get( repositoryType ), repoConfig );
153                         managedRepos.put( repo.getId( ), repo );
154                     }
155                     catch ( Exception e )
156                     {
157                         log.error( "Could not create managed repository {}: {}", repoConfig.getId( ), e.getMessage( ), e );
158                     }
159                 }
160             }
161             return managedRepos;
162         } catch (Throwable e) {
163             log.error("Could not initialize repositories from config: {}",e.getMessage(), e );
164             //noinspection unchecked
165             return Collections.EMPTY_MAP;
166         }
167     }
168
169     private ManagedRepository createNewManagedRepository( RepositoryProvider provider, ManagedRepositoryConfiguration cfg ) throws RepositoryException
170     {
171         ManagedRepository repo = provider.createManagedInstance( cfg );
172         updateRepositoryReferences( provider, repo, cfg , null);
173         return repo;
174
175     }
176
177     private void updateRepositoryReferences(RepositoryProvider provider, ManagedRepository repo, ManagedRepositoryConfiguration cfg, Configuration configuration) throws RepositoryException
178     {
179         if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
180         {
181             StagingRepositoryFeature feature = repo.getFeature( StagingRepositoryFeature.class ).get( );
182             if ( feature.isStageRepoNeeded( ) && feature.getStagingRepository() == null)
183             {
184                 ManagedRepository stageRepo = getStagingRepository( provider, cfg, configuration);
185                 managedRepositories.put(stageRepo.getId(), stageRepo);
186                 feature.setStagingRepository( stageRepo );
187                 if (configuration!=null) {
188                     replaceOrAddRepositoryConfig( provider.getManagedConfiguration( stageRepo ), configuration );
189                 }
190             }
191         }
192         if ( repo instanceof EditableManagedRepository && repo.getContent() == null)
193         {
194             ( (EditableManagedRepository) repo ).setContent( repositoryContentFactory.getManagedRepositoryContent( cfg, repo ) );
195         }
196     }
197
198     private ManagedRepository getStagingRepository(RepositoryProvider provider, ManagedRepositoryConfiguration baseRepoCfg, Configuration configuration) throws RepositoryException
199     {
200         ManagedRepository stageRepo = getManagedRepository( baseRepoCfg.getId( ) + StagingRepositoryFeature.STAGING_REPO_POSTFIX );
201         if ( stageRepo == null )
202         {
203             stageRepo = provider.createStagingInstance( baseRepoCfg );
204             ManagedRepositoryConfiguration stageCfg = provider.getManagedConfiguration( stageRepo );
205             updateRepositoryReferences( provider, stageRepo, stageCfg, configuration);
206         }
207         return stageRepo;
208     }
209
210
211
212
213     private Map<String, RemoteRepository> getRemoteRepositoriesFromConfig( )
214     {
215         try
216         {
217             List<RemoteRepositoryConfiguration> remoteRepoConfigs =
218                 getArchivaConfiguration( ).getConfiguration( ).getRemoteRepositories( );
219
220             if ( remoteRepoConfigs == null )
221             {
222                 //noinspection unchecked
223                 return Collections.EMPTY_MAP;
224             }
225
226             Map<String, RemoteRepository> remoteRepos = new LinkedHashMap<>( remoteRepoConfigs.size( ) );
227
228             Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap( );
229             for ( RemoteRepositoryConfiguration repoConfig : remoteRepoConfigs )
230             {
231                 RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
232                 if ( providerMap.containsKey( repositoryType ) )
233                 {
234                     RepositoryProvider provider = getProvider( repositoryType );
235                     try
236                     {
237
238                         RemoteRepository remoteRepository = createNewRemoteRepository( provider, repoConfig );
239                         remoteRepos.put( repoConfig.getId( ), remoteRepository);
240                     }
241                     catch ( Exception e )
242                     {
243                         log.error( "Could not create repository {} from config: {}", repoConfig.getId( ), e.getMessage( ), e );
244                     }
245                 }
246             }
247
248             return remoteRepos;
249         } catch (Throwable e) {
250             log.error("Could not initialize remote repositories from config: {}", e.getMessage(), e);
251             //noinspection unchecked
252             return Collections.EMPTY_MAP;
253         }
254     }
255
256     private RemoteRepository createNewRemoteRepository( RepositoryProvider provider, RemoteRepositoryConfiguration cfg ) throws RepositoryException
257     {
258         RemoteRepository repo = provider.createRemoteInstance( cfg );
259         updateRepositoryReferences( provider, repo, cfg , null);
260         return repo;
261
262     }
263
264     private void updateRepositoryReferences( RepositoryProvider provider, RemoteRepository repo, RemoteRepositoryConfiguration cfg, Configuration configuration) throws RepositoryException
265     {
266         if ( repo instanceof EditableRemoteRepository && repo.getContent() == null)
267         {
268             ( (EditableRemoteRepository) repo ).setContent( repositoryContentFactory.getRemoteRepositoryContent( cfg, repo ) );
269         }
270     }
271
272     private ArchivaConfiguration getArchivaConfiguration( )
273     {
274         return this.archivaConfiguration;
275     }
276
277     /**
278      * Returns all repositories that are registered. There is no defined order of the returned repositories.
279      *
280      * @return a list of managed and remote repositories
281      */
282     public Collection<Repository> getRepositories( )
283     {
284         rwLock.readLock( ).lock( );
285         try
286         {
287             return Stream.concat( managedRepositories.values( ).stream( ), remoteRepositories.values( ).stream( ) ).collect( Collectors.toList( ) );
288         }
289         finally
290         {
291             rwLock.readLock( ).unlock( );
292         }
293     }
294
295     /**
296      * Returns only the managed repositories. There is no defined order of the returned repositories.
297      *
298      * @return a list of managed repositories
299      */
300     public Collection<ManagedRepository> getManagedRepositories( )
301     {
302         rwLock.readLock().lock();
303         try
304         {
305             return uManagedRepository.values( );
306         } finally
307         {
308             rwLock.readLock().unlock();
309         }
310     }
311
312     /**
313      * Returns only the remote repositories. There is no defined order of the returned repositories.
314      *
315      * @return a list of remote repositories
316      */
317     public Collection<RemoteRepository> getRemoteRepositories( )
318     {
319         rwLock.readLock().lock();
320         try
321         {
322             return uRemoteRepositories.values( );
323         } finally
324         {
325             rwLock.readLock().unlock();
326         }
327     }
328
329     /**
330      * Returns the repository with the given id. The returned repository may be a managed or remote repository.
331      * It returns null, if no repository is registered with the given id.
332      *
333      * @param repoId the repository id
334      * @return the repository if found, otherwise null
335      */
336     public Repository getRepository( String repoId )
337     {
338         rwLock.readLock( ).lock( );
339         try
340         {
341             if ( managedRepositories.containsKey( repoId ) )
342             {
343                 return managedRepositories.get( repoId );
344             }
345             else
346             {
347                 return remoteRepositories.get( repoId );
348             }
349         }
350         finally
351         {
352             rwLock.readLock( ).unlock( );
353         }
354     }
355
356     /**
357      * Convenience method, that returns the managed repository with the given id.
358      * It returns null, if no managed repository is registered with this id.
359      *
360      * @param repoId the repository id
361      * @return the managed repository if found, otherwise null
362      */
363     public ManagedRepository getManagedRepository( String repoId )
364     {
365         rwLock.readLock( ).lock( );
366         try
367         {
368             return managedRepositories.get( repoId );
369         }
370         finally
371         {
372             rwLock.readLock( ).unlock( );
373         }
374     }
375
376     /**
377      * Convenience method, that returns the remote repository with the given id.
378      * It returns null, if no remote repository is registered with this id.
379      *
380      * @param repoId the repository id
381      * @return the remote repository if found, otherwise null
382      */
383     public RemoteRepository getRemoteRepository( String repoId )
384     {
385         rwLock.readLock( ).lock( );
386         try
387         {
388             return remoteRepositories.get( repoId );
389         }
390         finally
391         {
392             rwLock.readLock( ).unlock( );
393         }
394     }
395
396     /**
397      * Adds a new repository to the current list, or replaces the repository definition with
398      * the same id, if it exists already.
399      * The change is saved to the configuration immediately.
400      *
401      * @param managedRepository the new repository.
402      * @throws RepositoryException if the new repository could not be saved to the configuration.
403      */
404     public ManagedRepository putRepository( ManagedRepository managedRepository ) throws RepositoryException
405     {
406         rwLock.writeLock( ).lock( );
407         try
408         {
409             final String id = managedRepository.getId();
410             if (remoteRepositories.containsKey( id )) {
411                 throw new RepositoryException( "There exists a remote repository with id "+id+". Could not update with managed repository." );
412             }
413
414             ManagedRepository originRepo = managedRepositories.put( id, managedRepository );
415             try
416             {
417                 RepositoryProvider provider = getProvider( managedRepository.getType() );
418                 ManagedRepositoryConfiguration newCfg = provider.getManagedConfiguration( managedRepository );
419                 Configuration configuration = getArchivaConfiguration( ).getConfiguration( );
420                 updateRepositoryReferences( provider, managedRepository, newCfg, configuration );
421                 ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( id );
422                 if (oldCfg!=null) {
423                     configuration.removeManagedRepository( oldCfg );
424                 }
425                 configuration.addManagedRepository( newCfg );
426                 getArchivaConfiguration( ).save( configuration );
427                 return managedRepository;
428             }
429             catch ( Exception e )
430             {
431                 // Rollback
432                 if ( originRepo != null )
433                 {
434                     managedRepositories.put( id, originRepo );
435                 } else {
436                     managedRepositories.remove(id);
437                 }
438                 log.error("Exception during configuration update {}", e.getMessage(), e);
439                 throw new RepositoryException( "Could not save the configuration" + (e.getMessage( )==null?"":": "+e.getMessage()) );
440             }
441         }
442         finally
443         {
444             rwLock.writeLock( ).unlock( );
445         }
446     }
447
448     /**
449      * Adds a new repository or updates the repository with the same id, if it exists already.
450      * The configuration is saved immediately.
451      *
452      * @param managedRepositoryConfiguration the repository configuration
453      * @return the updated or created repository
454      * @throws RepositoryException if an error occurs, or the configuration is not valid.
455      */
456     public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration) throws RepositoryException
457     {
458         rwLock.writeLock( ).lock( );
459         try
460         {
461             final String id = managedRepositoryConfiguration.getId();
462             final RepositoryType repositoryType = RepositoryType.valueOf( managedRepositoryConfiguration.getType() );
463             Configuration configuration = getArchivaConfiguration().getConfiguration();
464             ManagedRepository repo = managedRepositories.get(id);
465             ManagedRepositoryConfiguration oldCfg = repo!=null ? getProvider( repositoryType ).getManagedConfiguration( repo ) : null;
466             repo = putRepository( managedRepositoryConfiguration, configuration );
467             try
468             {
469                 getArchivaConfiguration().save(configuration);
470             }
471             catch ( IndeterminateConfigurationException | RegistryException e )
472             {
473                 if (oldCfg!=null) {
474                     getProvider( repositoryType ).updateManagedInstance( (EditableManagedRepository)repo, oldCfg );
475                 }
476                 log.error("Could not save the configuration for repository {}: {}", id, e.getMessage(),e );
477                 throw new RepositoryException( "Could not save the configuration for repository "+id+": "+e.getMessage() );
478             }
479             return repo;
480         }
481         finally
482         {
483             rwLock.writeLock( ).unlock( );
484         }
485
486     }
487
488     /**
489      * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
490      * the configuration is not saved.
491      *
492      * @param managedRepositoryConfiguration the new or changed repository configuration
493      * @param configuration the configuration object
494      * @return the new or updated repository
495      * @throws RepositoryException if the configuration cannot be saved or updated
496      */
497     public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration) throws RepositoryException
498     {
499         rwLock.writeLock( ).lock( );
500         try
501         {
502             final String id = managedRepositoryConfiguration.getId();
503             final RepositoryType repoType = RepositoryType.valueOf( managedRepositoryConfiguration.getType() );
504             ManagedRepository repo;
505             if (managedRepositories.containsKey( id )) {
506                 repo = managedRepositories.get(id);
507                 if (repo instanceof EditableManagedRepository)
508                 {
509                     getProvider( repoType ).updateManagedInstance( (EditableManagedRepository) repo, managedRepositoryConfiguration );
510                 } else {
511                     throw new RepositoryException( "The repository is not editable "+id );
512                 }
513             } else
514             {
515                 repo = getProvider( repoType ).createManagedInstance( managedRepositoryConfiguration );
516                 managedRepositories.put(id, repo);
517             }
518             updateRepositoryReferences( getProvider( repoType  ), repo, managedRepositoryConfiguration, configuration );
519             replaceOrAddRepositoryConfig( managedRepositoryConfiguration, configuration );
520             return repo;
521         }
522         finally
523         {
524             rwLock.writeLock( ).unlock( );
525         }
526     }
527
528     private void replaceOrAddRepositoryConfig(ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration) {
529         ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( managedRepositoryConfiguration.getId() );
530         if ( oldCfg !=null) {
531             configuration.removeManagedRepository( oldCfg );
532         }
533         configuration.addManagedRepository( managedRepositoryConfiguration );
534     }
535
536     private void replaceOrAddRepositoryConfig(RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration) {
537         RemoteRepositoryConfiguration oldCfg = configuration.findRemoteRepositoryById( remoteRepositoryConfiguration.getId() );
538         if ( oldCfg !=null) {
539             configuration.removeRemoteRepository( oldCfg );
540         }
541         configuration.addRemoteRepository( remoteRepositoryConfiguration );
542     }
543
544     public RemoteRepository putRepository( RemoteRepository remoteRepository, Configuration configuration) throws RepositoryException
545     {
546         rwLock.writeLock( ).lock( );
547         try
548         {
549             final String id = remoteRepository.getId();
550             if (managedRepositories.containsKey( id )) {
551                 throw new RepositoryException( "There exists a managed repository with id "+id+". Could not update with remote repository." );
552             }
553             RemoteRepository originRepo = remoteRepositories.put( id, remoteRepository );
554             RemoteRepositoryConfiguration oldCfg=null;
555             RemoteRepositoryConfiguration newCfg=null;
556             try
557             {
558                 final RepositoryProvider provider = getProvider( remoteRepository.getType() );
559                 newCfg = provider.getRemoteConfiguration( remoteRepository );
560                 updateRepositoryReferences( provider, remoteRepository, newCfg, configuration );
561                 oldCfg = configuration.findRemoteRepositoryById( id );
562                 if (oldCfg!=null) {
563                     configuration.removeRemoteRepository( oldCfg );
564                 }
565                 configuration.addRemoteRepository( newCfg );
566                 return remoteRepository;
567             }
568             catch ( Exception e )
569             {
570                 // Rollback
571                 if ( originRepo != null )
572                 {
573                     remoteRepositories.put( id, originRepo );
574                 } else {
575                     remoteRepositories.remove( id);
576                 }
577                 if (oldCfg!=null) {
578                     RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( id );
579                     if (cfg!=null) {
580                         configuration.removeRemoteRepository( cfg );
581                         configuration.addRemoteRepository( oldCfg );
582                     }
583                 }
584                 log.error("Error while adding remote repository {}", e.getMessage(), e);
585                 throw new RepositoryException( "Could not save the configuration" + (e.getMessage( )==null?"":": "+e.getMessage()) );
586             }
587         }
588         finally
589         {
590             rwLock.writeLock( ).unlock( );
591         }
592     }
593
594     /**
595      * Adds a remote repository, or overwrites the repository definition with the same id, if it exists already.
596      * The modification is saved to the configuration immediately.
597      *
598      * @param remoteRepository the remote repository to add
599      * @throws RepositoryException if an error occurs during configuration save
600      */
601     public RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException
602     {
603         rwLock.writeLock( ).lock( );
604         try
605         {
606             Configuration configuration = getArchivaConfiguration().getConfiguration();
607             try
608             {
609                 RemoteRepository repo = putRepository( remoteRepository, configuration );
610                 getArchivaConfiguration().save(configuration);
611                 return repo;
612             }
613             catch ( RegistryException | IndeterminateConfigurationException e )
614             {
615                 log.error("Error while saving remote repository {}", e.getMessage(), e);
616                 throw new RepositoryException( "Could not save the configuration" + (e.getMessage( )==null?"":": "+e.getMessage()) );
617             }
618         }
619         finally
620         {
621             rwLock.writeLock( ).unlock( );
622         }
623     }
624
625     /**
626      * Adds a new repository or updates the repository with the same id, if it exists already.
627      * The configuration is saved immediately.
628      *
629      * @param remoteRepositoryConfiguration the repository configuration
630      * @return the updated or created repository
631      * @throws RepositoryException if an error occurs, or the configuration is not valid.
632      */
633     public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration) throws RepositoryException
634     {
635         rwLock.writeLock( ).lock( );
636         try
637         {
638             final String id = remoteRepositoryConfiguration.getId();
639             final RepositoryType repositoryType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType() );
640             Configuration configuration = getArchivaConfiguration().getConfiguration();
641             RemoteRepository repo = remoteRepositories.get(id);
642             RemoteRepositoryConfiguration oldCfg = repo!=null ? getProvider( repositoryType ).getRemoteConfiguration( repo ) : null;
643             repo = putRepository( remoteRepositoryConfiguration, configuration );
644             try
645             {
646                 getArchivaConfiguration().save(configuration);
647             }
648             catch ( IndeterminateConfigurationException | RegistryException e )
649             {
650                 if (oldCfg!=null) {
651                     getProvider( repositoryType ).updateRemoteInstance( (EditableRemoteRepository)repo, oldCfg );
652                 }
653                 log.error("Could not save the configuration for repository {}: {}", id, e.getMessage(),e );
654                 throw new RepositoryException( "Could not save the configuration for repository "+id+": "+e.getMessage() );
655             }
656             return repo;
657         }
658         finally
659         {
660             rwLock.writeLock( ).unlock( );
661         }
662
663     }
664
665     /**
666      * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
667      * the configuration is not saved.
668      *
669      * @param remoteRepositoryConfiguration the new or changed repository configuration
670      * @param configuration the configuration object
671      * @return the new or updated repository
672      * @throws RepositoryException if the configuration cannot be saved or updated
673      */
674     public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration) throws RepositoryException
675     {
676         rwLock.writeLock( ).lock( );
677         try
678         {
679             final String id = remoteRepositoryConfiguration.getId();
680             final RepositoryType repoType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType() );
681             RemoteRepository repo;
682             if (remoteRepositories.containsKey( id )) {
683                 repo = remoteRepositories.get(id);
684                 if (repo instanceof EditableRemoteRepository)
685                 {
686                     getProvider( repoType ).updateRemoteInstance( (EditableRemoteRepository) repo, remoteRepositoryConfiguration );
687                 } else {
688                     throw new RepositoryException( "The repository is not editable "+id );
689                 }
690             } else
691             {
692                 repo = getProvider( repoType ).createRemoteInstance( remoteRepositoryConfiguration );
693                 remoteRepositories.put(id, repo);
694             }
695             updateRepositoryReferences( getProvider( repoType  ), repo, remoteRepositoryConfiguration, configuration );
696             replaceOrAddRepositoryConfig( remoteRepositoryConfiguration, configuration );
697             return repo;
698         }
699         finally
700         {
701             rwLock.writeLock( ).unlock( );
702         }
703
704
705     }
706
707     public void removeRepository(Repository repo) throws RepositoryException
708     {
709         if (repo instanceof RemoteRepository ) {
710             removeRepository( (RemoteRepository)repo );
711         } else if (repo instanceof ManagedRepository) {
712             removeRepository( (ManagedRepository)repo);
713         } else {
714             throw new RepositoryException( "Repository type not known: "+repo.getClass() );
715         }
716     }
717
718     /**
719      * Removes a managed repository from the registry and configuration, if it exists.
720      * The change is saved to the configuration immediately.
721      *
722      * @param managedRepository the managed repository to remove
723      * @throws RepositoryException if a error occurs during configuration save
724      */
725     public void removeRepository( ManagedRepository managedRepository ) throws RepositoryException
726     {
727         final String id = managedRepository.getId();
728         ManagedRepository repo = getManagedRepository( id );
729         if (repo!=null) {
730             rwLock.writeLock().lock();
731             try {
732                 repo = managedRepositories.remove( id );
733                 if (repo!=null) {
734                     Configuration configuration = getArchivaConfiguration().getConfiguration();
735                     ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById( id );
736                     if (cfg!=null) {
737                         configuration.removeManagedRepository( cfg );
738                     }
739                     getArchivaConfiguration().save( configuration );
740                 }
741
742             }
743             catch ( RegistryException | IndeterminateConfigurationException e )
744             {
745                 // Rollback
746                 log.error("Could not save config after repository removal: {}", e.getMessage(), e);
747                 managedRepositories.put(repo.getId(), repo);
748                 throw new RepositoryException( "Could not save configuration after repository removal: "+e.getMessage() );
749             }
750             finally
751             {
752                 rwLock.writeLock().unlock();
753             }
754         }
755     }
756
757     public void removeRepository(ManagedRepository managedRepository, Configuration configuration) throws RepositoryException
758     {
759         final String id = managedRepository.getId();
760         ManagedRepository repo = getManagedRepository( id );
761         if (repo!=null) {
762             rwLock.writeLock().lock();
763             try {
764                 repo = managedRepositories.remove( id );
765                 if (repo!=null) {
766                     ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById( id );
767                     if (cfg!=null) {
768                         configuration.removeManagedRepository( cfg );
769                     }
770                 }
771             }
772             finally
773             {
774                 rwLock.writeLock().unlock();
775             }
776         }
777
778     }
779
780     /**
781      * Removes the remote repository from the registry and configuration.
782      * The change is saved to the configuration immediately.
783      *
784      * @param remoteRepository the remote repository to remove
785      * @throws RepositoryException if a error occurs during configuration save
786      */
787     public void removeRepository( RemoteRepository remoteRepository ) throws RepositoryException
788     {
789         final String id = remoteRepository.getId();
790         RemoteRepository repo = getRemoteRepository( id );
791         if (repo!=null) {
792             rwLock.writeLock().lock();
793             try {
794                 repo = remoteRepositories.remove( id );
795                 if (repo!=null) {
796                     Configuration configuration = getArchivaConfiguration().getConfiguration();
797                     RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( id );
798                     if (cfg!=null) {
799                         configuration.removeRemoteRepository( cfg );
800                     }
801                     getArchivaConfiguration().save( configuration );
802                 }
803
804             }
805             catch ( RegistryException | IndeterminateConfigurationException e )
806             {
807                 // Rollback
808                 log.error("Could not save config after repository removal: {}", e.getMessage(), e);
809                 remoteRepositories.put(repo.getId(), repo);
810                 throw new RepositoryException( "Could not save configuration after repository removal: "+e.getMessage() );
811             }
812             finally
813             {
814                 rwLock.writeLock().unlock();
815             }
816         }
817     }
818
819     public void removeRepository( RemoteRepository remoteRepository, Configuration configuration) throws RepositoryException
820     {
821         final String id = remoteRepository.getId();
822         RemoteRepository repo = getRemoteRepository( id );
823         if (repo!=null) {
824             rwLock.writeLock().lock();
825             try {
826                 repo = remoteRepositories.remove( id );
827                 if (repo!=null) {
828                     RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( id );
829                     if (cfg!=null) {
830                         configuration.removeRemoteRepository( cfg );
831                     }
832                 }
833             }
834             finally
835             {
836                 rwLock.writeLock().unlock();
837             }
838         }
839
840     }
841
842     /**
843      * Reloads the registry from the configuration.
844      */
845     public void reload() {
846         initialize();
847     }
848
849
850     /**
851      * Creates a new repository instance with the same settings as this one. The cloned repository is not
852      * registered or saved to the configuration.
853      *
854      * @param repo The origin repository
855      * @return The cloned repository.
856      */
857     public ManagedRepository clone(ManagedRepository repo, String newId) throws RepositoryException
858     {
859         if (managedRepositories.containsKey(newId) || remoteRepositories.containsKey(newId)) {
860             throw new RepositoryException("The given id exists already "+newId);
861         }
862         RepositoryProvider provider = getProvider(repo.getType());
863         ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration(repo);
864         cfg.setId(newId);
865         ManagedRepository cloned = provider.createManagedInstance(cfg);
866         return cloned;
867     }
868
869     public <T extends Repository> Repository clone(T repo, String newId) throws RepositoryException {
870         if (repo instanceof RemoteRepository ) {
871             return this.clone((RemoteRepository)repo, newId);
872         } else if (repo instanceof ManagedRepository) {
873             return this.clone((ManagedRepository)repo, newId);
874         } else {
875             throw new RepositoryException("This repository class is not supported "+ repo.getClass().getName());
876         }
877     }
878
879     /**
880      * Creates a new repository instance with the same settings as this one. The cloned repository is not
881      * registered or saved to the configuration.
882      *
883      * @param repo The origin repository
884      * @return The cloned repository.
885      */
886     public RemoteRepository clone( RemoteRepository repo, String newId) throws RepositoryException
887     {
888         if (managedRepositories.containsKey(newId) || remoteRepositories.containsKey(newId)) {
889             throw new RepositoryException("The given id exists already "+newId);
890         }
891         RepositoryProvider provider = getProvider(repo.getType());
892         RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration(repo);
893         cfg.setId(newId);
894         RemoteRepository cloned = provider.createRemoteInstance(cfg);
895         return cloned;
896     }
897
898
899     @Override
900     public void configurationEvent(ConfigurationEvent event) {
901
902     }
903 }