]> source.dussan.org Git - archiva.git/blob
bdcbf04d80342673264bfbd8820d7496bb559087
[archiva.git] /
1 package org.apache.archiva.repository.base.managed;
2 /*
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19
20 import org.apache.archiva.components.registry.RegistryException;
21 import org.apache.archiva.configuration.model.Configuration;
22 import org.apache.archiva.configuration.provider.IndeterminateConfigurationException;
23 import org.apache.archiva.configuration.model.ManagedRepositoryConfiguration;
24 import org.apache.archiva.indexer.ArchivaIndexManager;
25 import org.apache.archiva.indexer.IndexCreationFailedException;
26 import org.apache.archiva.indexer.IndexManagerFactory;
27 import org.apache.archiva.repository.EditableManagedRepository;
28 import org.apache.archiva.repository.EditableRepository;
29 import org.apache.archiva.repository.ManagedRepository;
30 import org.apache.archiva.repository.RepositoryContentFactory;
31 import org.apache.archiva.repository.RepositoryException;
32 import org.apache.archiva.repository.RepositoryHandler;
33 import org.apache.archiva.repository.RepositoryHandlerManager;
34 import org.apache.archiva.repository.RepositoryProvider;
35 import org.apache.archiva.repository.RepositoryState;
36 import org.apache.archiva.repository.RepositoryType;
37 import org.apache.archiva.repository.base.AbstractRepositoryHandler;
38 import org.apache.archiva.repository.base.ConfigurationHandler;
39 import org.apache.archiva.repository.event.LifecycleEvent;
40 import org.apache.archiva.repository.event.RepositoryEvent;
41 import org.apache.archiva.repository.features.IndexCreationFeature;
42 import org.apache.archiva.repository.features.StagingRepositoryFeature;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.springframework.stereotype.Service;
46
47 import javax.annotation.PostConstruct;
48 import javax.inject.Named;
49 import java.io.IOException;
50 import java.util.ArrayList;
51 import java.util.Collections;
52 import java.util.HashMap;
53 import java.util.List;
54 import java.util.Map;
55 import java.util.concurrent.locks.ReentrantReadWriteLock;
56
57 /**
58  * Handler implementation for managed repositories.
59  *
60  * @author Martin Stockhammer <martin_s@apache.org>
61  */
62 @Service( "managedRepositoryHandler#default" )
63 public class ManagedRepositoryHandler
64     extends AbstractRepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration>
65     implements RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration>
66 {
67     private static final Logger log = LoggerFactory.getLogger( ManagedRepositoryHandler.class );
68     private final RepositoryHandlerManager repositoryHandlerManager;
69     private final RepositoryContentFactory repositoryContentFactory;
70
71
72     IndexManagerFactory indexManagerFactory;
73
74
75     public ManagedRepositoryHandler( RepositoryHandlerManager repositoryHandlerManager,
76                                      ConfigurationHandler configurationHandler, IndexManagerFactory indexManagerFactory,
77                                      @Named( "repositoryContentFactory#default" )
78                                          RepositoryContentFactory repositoryContentFactory
79     )
80     {
81         super( ManagedRepository.class, ManagedRepositoryConfiguration.class, configurationHandler );
82         this.repositoryHandlerManager = repositoryHandlerManager;
83         this.indexManagerFactory = indexManagerFactory;
84         this.repositoryContentFactory = repositoryContentFactory;
85     }
86
87     @Override
88     @PostConstruct
89     public void init( )
90     {
91         log.debug( "Initializing repository handler " + ManagedRepositoryHandler.class );
92         initializeStorage( );
93         // We are registering this class on the registry. This is necessary to avoid circular dependencies via injection.
94         this.repositoryHandlerManager.registerHandler( this );
95     }
96
97     private void initializeStorage( )
98     {
99
100     }
101
102     @Override
103     public void initializeFromConfig( )
104     {
105         Map<String, ManagedRepository> currentInstances = new HashMap<>( getRepositories( ) );
106         getRepositories().clear();
107         getRepositories( ).putAll( newOrUpdateInstancesFromConfig( currentInstances ) );
108         for ( ManagedRepository managedRepository : getRepositories( ).values( ) )
109         {
110             activateRepository( managedRepository );
111         }
112         for (ManagedRepository managedRepository : currentInstances.values()) {
113             deactivateRepository( managedRepository );
114         }
115
116     }
117
118     @Override
119     public Map<String, ManagedRepository> newInstancesFromConfig( )
120     {
121         try
122         {
123             List<ManagedRepositoryConfiguration> managedRepoConfigs =
124                 new ArrayList<>(
125                     getConfigurationHandler( ).getBaseConfiguration( ).getManagedRepositories( ) );
126
127             if ( managedRepoConfigs == null )
128             {
129                 return Collections.emptyMap( );
130             }
131
132             Map<String, ManagedRepository> result = new HashMap<>( );
133             for ( ManagedRepositoryConfiguration repoConfig : managedRepoConfigs )
134             {
135                 ManagedRepository repo = newInstance( repoConfig );
136                 result.put( repo.getId( ), repo );
137                 if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
138                 {
139                     StagingRepositoryFeature stagF = repo.getFeature( StagingRepositoryFeature.class ).get( );
140                     if ( stagF.getStagingRepository( ) != null )
141                     {
142                         ManagedRepository stagingRepo = getStagingRepository( repo );
143                         if ( stagingRepo != null )
144                         {
145                             result.put( stagingRepo.getId( ), stagingRepo );
146                         }
147                     }
148                 }
149             }
150             return result;
151         }
152         catch ( Throwable e )
153         {
154             log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
155             return new HashMap<>( );
156         }
157     }
158
159     public Map<String, ManagedRepository> newOrUpdateInstancesFromConfig( Map<String, ManagedRepository> currentInstances)
160     {
161         try
162         {
163             List<ManagedRepositoryConfiguration> managedRepoConfigs =
164                 new ArrayList<>(
165                     getConfigurationHandler( ).getBaseConfiguration( ).getManagedRepositories( ) );
166
167             if ( managedRepoConfigs == null )
168             {
169                 return Collections.emptyMap( );
170             }
171
172             Map<String, ManagedRepository> result = new HashMap<>( );
173             for ( ManagedRepositoryConfiguration repoConfig : managedRepoConfigs )
174             {
175                 String id = repoConfig.getId( );
176                 if (result.containsKey( id )) {
177                     log.error( "There are repositories with the same id in the configuration: {}", id );
178                     continue;
179                 }
180                 ManagedRepository repo;
181                 if ( currentInstances.containsKey( id ) )
182                 {
183                     repo = currentInstances.remove( id );
184                     getProvider( repo.getType() ).updateManagedInstance( (EditableManagedRepository) repo, repoConfig );
185                     updateReferences( repo, repoConfig );
186                 }
187                 else
188                 {
189                     repo = newInstance( repoConfig );
190                 }
191                 result.put( id, repo );
192                 if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
193                 {
194                     StagingRepositoryFeature stagF = repo.getFeature( StagingRepositoryFeature.class ).get( );
195                     if ( stagF.getStagingRepository( ) != null )
196                     {
197                         String stagingId = getStagingId( id );
198                         ManagedRepository stagingRepo;
199                         if ( currentInstances.containsKey( stagingId ) )
200                         {
201                             stagingRepo = currentInstances.remove( stagingId );
202                             managedRepoConfigs.stream( ).filter( cfg -> stagingId.equals( cfg.getId( ) ) ).findFirst( ).ifPresent(
203                                 stagingRepoConfig ->
204                                 {
205                                     try
206                                     {
207                                         getProvider( stagingRepo.getType() ).updateManagedInstance( (EditableManagedRepository) stagingRepo, stagingRepoConfig );
208                                         updateReferences( stagingRepo, stagingRepoConfig );
209                                     }
210                                     catch ( RepositoryException e )
211                                     {
212                                         log.error( "Could not update staging repo {}: {}", stagingId, e.getMessage( ) );
213                                     }
214                                 }
215                             );
216                         }
217                         else
218                         {
219                             stagingRepo = getStagingRepository( repo );
220                         }
221                         if ( stagingRepo != null )
222                         {
223                             result.put( stagingRepo.getId( ), stagingRepo );
224                         }
225                     }
226                 }
227             }
228             return result;
229         }
230         catch ( Throwable e )
231         {
232             log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
233             return new HashMap<>( );
234         }
235     }
236
237
238     @Override
239     public ManagedRepository newInstance( RepositoryType type, String id ) throws RepositoryException
240     {
241         log.debug( "Creating repo {}", id );
242         RepositoryProvider provider = getProvider( type );
243         EditableManagedRepository repo;
244         try
245         {
246             repo = provider.createManagedInstance( id, id );
247         }
248         catch ( IOException e )
249         {
250             throw new RepositoryException( "Could not create repository '" + id + "': " + e.getMessage( ) );
251         }
252         repo.registerEventHandler( RepositoryEvent.ANY, repositoryHandlerManager );
253         updateReferences( repo, null );
254         repo.setLastState( RepositoryState.REFERENCES_SET );
255         return repo;
256     }
257
258     private String getStagingId( String repoId )
259     {
260         return repoId + StagingRepositoryFeature.STAGING_REPO_POSTFIX;
261     }
262
263
264     private ManagedRepository getStagingRepository( ManagedRepository baseRepo ) throws RepositoryException
265     {
266         ManagedRepository stageRepo = get( getStagingId( baseRepo.getId( ) ) );
267         final RepositoryType type = baseRepo.getType( );
268         if ( stageRepo == null )
269         {
270             RepositoryProvider provider = getProvider( type );
271             ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration( baseRepo );
272             stageRepo = provider.createStagingInstance( cfg );
273             if ( stageRepo.supportsFeature( StagingRepositoryFeature.class ) )
274             {
275                 stageRepo.getFeature( StagingRepositoryFeature.class ).get( ).setStageRepoNeeded( false );
276             }
277             updateReferences( stageRepo, cfg );
278         }
279         return stageRepo;
280     }
281
282     public ArchivaIndexManager getIndexManager( RepositoryType type )
283     {
284         return indexManagerFactory.getIndexManager( type );
285     }
286
287     private void createIndexingContext( EditableRepository editableRepo ) throws RepositoryException
288     {
289         if ( editableRepo.supportsFeature( IndexCreationFeature.class ) )
290         {
291             ArchivaIndexManager idxManager = getIndexManager( editableRepo.getType( ) );
292             try
293             {
294                 editableRepo.setIndexingContext( idxManager.createContext( editableRepo ) );
295                 idxManager.updateLocalIndexPath( editableRepo );
296             }
297             catch ( IndexCreationFailedException e )
298             {
299                 throw new RepositoryException( "Could not create index for repository " + editableRepo.getId( ) + ": " + e.getMessage( ), e );
300             }
301         }
302     }
303
304
305     @Override
306     public ManagedRepository newInstance( ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
307     {
308         RepositoryType type = RepositoryType.valueOf( repositoryConfiguration.getType( ) );
309         RepositoryProvider provider = getProvider( type );
310         if ( provider == null )
311         {
312             throw new RepositoryException( "Provider not found for repository type: " + repositoryConfiguration.getType( ) );
313         }
314         final ManagedRepository repo = provider.createManagedInstance( repositoryConfiguration );
315         repo.registerEventHandler( RepositoryEvent.ANY, repositoryHandlerManager );
316         updateReferences( repo, null );
317         if ( repo instanceof EditableRepository )
318         {
319             ( (EditableRepository) repo ).setLastState( RepositoryState.REFERENCES_SET );
320         }
321         return repo;
322     }
323
324     @Override
325     protected ManagedRepositoryConfiguration findRepositoryConfiguration( final Configuration configuration, final String id )
326     {
327         return configuration.findManagedRepositoryById( id );
328     }
329
330     @Override
331     protected void removeRepositoryConfiguration( final Configuration configuration, final ManagedRepositoryConfiguration repoConfiguration )
332     {
333         configuration.removeManagedRepository( repoConfiguration );
334     }
335
336     @Override
337     protected void addRepositoryConfiguration( Configuration configuration, ManagedRepositoryConfiguration repoConfiguration )
338     {
339         configuration.addManagedRepository( repoConfiguration );
340     }
341
342     @Override
343     public ManagedRepository put( ManagedRepository repository ) throws RepositoryException
344     {
345         final String id = repository.getId( );
346         ManagedRepository originRepo = getRepositories( ).remove( id );
347         if ( originRepo == null && repositoryHandlerManager.isRegisteredId( id ) )
348         {
349             throw new RepositoryException( "There exists a repository with id " + id + ". Could not update with managed repository." );
350         }
351         try
352         {
353             if ( originRepo != null && repository != originRepo )
354             {
355                 deactivateRepository( originRepo );
356                 pushEvent( LifecycleEvent.UNREGISTERED, originRepo );
357             }
358             RepositoryProvider provider = getProvider( repository.getType( ) );
359             ManagedRepositoryConfiguration newCfg = provider.getManagedConfiguration( repository );
360             getConfigurationHandler( ).getLock( ).writeLock( ).lock( );
361             try
362             {
363                 Configuration configuration = getConfigurationHandler( ).getBaseConfiguration( );
364                 updateReferences( repository, newCfg );
365                 ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( id );
366                 if ( oldCfg != null )
367                 {
368                     configuration.removeManagedRepository( oldCfg );
369                 }
370                 configuration.addManagedRepository( newCfg );
371                 getConfigurationHandler( ).save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
372                 setLastState( repository, RepositoryState.SAVED );
373                 activateRepository( repository );
374             }
375             finally
376             {
377                 getConfigurationHandler( ).getLock( ).writeLock( ).unlock( );
378             }
379             getRepositories( ).put( id, repository );
380             setLastState( repository, RepositoryState.REGISTERED );
381             return repository;
382         }
383         catch ( Exception e )
384         {
385             // Rollback only partly, because repository is closed already
386             if ( originRepo != null )
387             {
388                 getRepositories( ).put( id, originRepo );
389             }
390             else
391             {
392                 getRepositories( ).remove( id );
393             }
394             log.error( "Exception during configuration update {}", e.getMessage( ), e );
395             throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ) );
396         }
397     }
398
399
400     @Override
401     public ManagedRepository put( ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
402     {
403         final String id = repositoryConfiguration.getId( );
404         final RepositoryType repositoryType = RepositoryType.valueOf( repositoryConfiguration.getType( ) );
405         final RepositoryProvider provider = getProvider( repositoryType );
406         ReentrantReadWriteLock.WriteLock configLock = this.getConfigurationHandler( ).getLock( ).writeLock( );
407         configLock.lock( );
408         ManagedRepository repo = null;
409         ManagedRepository oldRepository = null;
410         Configuration configuration = null;
411         try
412         {
413             boolean updated = false;
414             configuration = getConfigurationHandler( ).getBaseConfiguration( );
415             repo = getRepositories( ).get( id );
416             oldRepository = repo == null ? null : clone( repo, id );
417             if ( repo == null )
418             {
419                 repo = put( repositoryConfiguration, configuration );
420             }
421             else
422             {
423                 setRepositoryDefaults( repositoryConfiguration );
424                 provider.updateManagedInstance( (EditableManagedRepository) repo, repositoryConfiguration );
425                 updated = true;
426                 pushEvent( LifecycleEvent.UPDATED, repo );
427             }
428             registerNewRepository( repositoryConfiguration, repo, configuration, updated );
429         }
430         catch ( IndeterminateConfigurationException | RegistryException e )
431         {
432             if ( oldRepository != null )
433             {
434                 ManagedRepositoryConfiguration oldCfg = provider.getManagedConfiguration( oldRepository );
435                 provider.updateManagedInstance( (EditableManagedRepository) repo, oldCfg );
436                 rollback( configuration, oldRepository, e, oldCfg );
437             }
438             else
439             {
440                 getRepositories( ).remove( id );
441             }
442             log.error( "Could not save the configuration for repository {}: {}", id, e.getMessage( ), e );
443             throw new RepositoryException( "Could not save the configuration for repository " + id + ": " + e.getMessage( ) );
444         }
445         finally
446         {
447             configLock.unlock( );
448         }
449         return repo;
450     }
451
452     @Override
453     public ManagedRepository put( ManagedRepositoryConfiguration repositoryConfiguration, Configuration configuration ) throws RepositoryException
454     {
455         final String id = repositoryConfiguration.getId( );
456         final RepositoryType repoType = RepositoryType.valueOf( repositoryConfiguration.getType( ) );
457         ManagedRepository repo;
458         setRepositoryDefaults( repositoryConfiguration );
459         if ( getRepositories( ).containsKey( id ) )
460         {
461             repo = clone( getRepositories( ).get( id ), id );
462             if ( repo instanceof EditableManagedRepository )
463             {
464                 getProvider( repoType ).updateManagedInstance( (EditableManagedRepository) repo, repositoryConfiguration );
465             }
466             else
467             {
468                 throw new RepositoryException( "The repository is not editable " + id );
469             }
470         }
471         else
472         {
473             repo = getProvider( repoType ).createManagedInstance( repositoryConfiguration );
474             setLastState( repo, RepositoryState.CREATED );
475         }
476         if ( configuration != null )
477         {
478             replaceOrAddRepositoryConfig( repositoryConfiguration, configuration );
479         }
480         updateReferences( repo, repositoryConfiguration );
481         setLastState( repo, RepositoryState.REFERENCES_SET );
482         return repo;
483     }
484
485     @SuppressWarnings( "unused" )
486     private void setRepositoryDefaults( ManagedRepositoryConfiguration repositoryConfiguration )
487     {
488         // We do nothing here
489     }
490
491     @Override
492     public ManagedRepository clone( ManagedRepository repo, String id ) throws RepositoryException
493     {
494         RepositoryProvider provider = getProvider( repo.getType( ) );
495         ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration( repo );
496         cfg.setId( id );
497         ManagedRepository cloned = provider.createManagedInstance( cfg );
498         cloned.registerEventHandler( RepositoryEvent.ANY, repositoryHandlerManager );
499         setLastState( cloned, RepositoryState.CREATED );
500         return cloned;
501     }
502
503
504     @Override
505     public void updateReferences( ManagedRepository repo, ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
506     {
507         log.debug( "Updating references of repo {}", repo.getId( ) );
508         if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
509         {
510             Configuration configuration = getConfigurationHandler( ).getBaseConfiguration( );
511             RepositoryProvider provider = getProvider( repo.getType( ) );
512             StagingRepositoryFeature feature = repo.getFeature( StagingRepositoryFeature.class ).get( );
513             if ( feature.isStageRepoNeeded( ) && feature.getStagingRepository( ) == null )
514             {
515                 ManagedRepository stageRepo = get( getStagingId( repo.getId( ) ) );
516                 if ( stageRepo == null )
517                 {
518                     stageRepo = getStagingRepository( repo );
519                     getRepositories( ).put( stageRepo.getId( ), stageRepo );
520                     if ( configuration != null )
521                     {
522                         replaceOrAddRepositoryConfig( provider.getManagedConfiguration( stageRepo ), configuration );
523                     }
524                     pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, stageRepo ) );
525                 }
526                 feature.setStagingRepository( stageRepo );
527             }
528         }
529         if ( repo instanceof EditableManagedRepository )
530         {
531             EditableManagedRepository editableRepo = (EditableManagedRepository) repo;
532             if ( repo.getContent( ) == null )
533             {
534                 editableRepo.setContent( repositoryContentFactory.getManagedRepositoryContent( repo ) );
535                 editableRepo.getContent( ).setRepository( editableRepo );
536             }
537             log.debug( "Index repo: " + repo.hasIndex( ) );
538             if ( repo.hasIndex( ) && ( repo.getIndexingContext( ) == null || !repo.getIndexingContext( ).isOpen( ) ) )
539             {
540                 log.debug( "Creating indexing context for {}", repo.getId( ) );
541                 createIndexingContext( editableRepo );
542             }
543         }
544         repo.registerEventHandler( RepositoryEvent.ANY, repositoryHandlerManager );
545     }
546
547 }