1 package org.apache.archiva.repository.base.managed;
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
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
20 import org.apache.archiva.components.registry.RegistryException;
21 import org.apache.archiva.configuration.Configuration;
22 import org.apache.archiva.configuration.IndeterminateConfigurationException;
23 import org.apache.archiva.configuration.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;
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;
55 import java.util.concurrent.locks.ReentrantReadWriteLock;
58 * Handler implementation for managed repositories.
60 * @author Martin Stockhammer <martin_s@apache.org>
62 @Service( "managedRepositoryHandler#default" )
63 public class ManagedRepositoryHandler
64 extends AbstractRepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration>
65 implements RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration>
67 private static final Logger log = LoggerFactory.getLogger( ManagedRepositoryHandler.class );
68 private final RepositoryHandlerManager repositoryHandlerManager;
69 private final RepositoryContentFactory repositoryContentFactory;
72 IndexManagerFactory indexManagerFactory;
75 public ManagedRepositoryHandler( RepositoryHandlerManager repositoryHandlerManager,
76 ConfigurationHandler configurationHandler, IndexManagerFactory indexManagerFactory,
77 @Named( "repositoryContentFactory#default" )
78 RepositoryContentFactory repositoryContentFactory
81 super( ManagedRepository.class, ManagedRepositoryConfiguration.class, configurationHandler );
82 this.repositoryHandlerManager = repositoryHandlerManager;
83 this.indexManagerFactory = indexManagerFactory;
84 this.repositoryContentFactory = repositoryContentFactory;
91 log.debug( "Initializing repository handler " + ManagedRepositoryHandler.class );
93 // We are registering this class on the registry. This is necessary to avoid circular dependencies via injection.
94 this.repositoryHandlerManager.registerHandler( this );
97 private void initializeStorage( )
103 public void initializeFromConfig( )
105 Map<String, ManagedRepository> currentInstances = new HashMap<>( getRepositories( ) );
106 getRepositories().clear();
107 getRepositories( ).putAll( newOrUpdateInstancesFromConfig( currentInstances ) );
108 for ( ManagedRepository managedRepository : getRepositories( ).values( ) )
110 activateRepository( managedRepository );
112 for (ManagedRepository managedRepository : currentInstances.values()) {
113 deactivateRepository( managedRepository );
119 public Map<String, ManagedRepository> newInstancesFromConfig( )
123 List<ManagedRepositoryConfiguration> managedRepoConfigs =
125 getConfigurationHandler( ).getBaseConfiguration( ).getManagedRepositories( ) );
127 if ( managedRepoConfigs == null )
129 return Collections.emptyMap( );
132 Map<String, ManagedRepository> result = new HashMap<>( );
133 for ( ManagedRepositoryConfiguration repoConfig : managedRepoConfigs )
135 ManagedRepository repo = newInstance( repoConfig );
136 result.put( repo.getId( ), repo );
137 if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
139 StagingRepositoryFeature stagF = repo.getFeature( StagingRepositoryFeature.class ).get( );
140 if ( stagF.getStagingRepository( ) != null )
142 ManagedRepository stagingRepo = getStagingRepository( repo );
143 if ( stagingRepo != null )
145 result.put( stagingRepo.getId( ), stagingRepo );
152 catch ( Throwable e )
154 log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
155 return new HashMap<>( );
159 public Map<String, ManagedRepository> newOrUpdateInstancesFromConfig( Map<String, ManagedRepository> currentInstances)
163 List<ManagedRepositoryConfiguration> managedRepoConfigs =
165 getConfigurationHandler( ).getBaseConfiguration( ).getManagedRepositories( ) );
167 if ( managedRepoConfigs == null )
169 return Collections.emptyMap( );
172 Map<String, ManagedRepository> result = new HashMap<>( );
173 for ( ManagedRepositoryConfiguration repoConfig : managedRepoConfigs )
175 String id = repoConfig.getId( );
176 if (result.containsKey( id )) {
177 log.error( "There are repositories with the same id in the configuration: {}", id );
180 ManagedRepository repo;
181 if ( currentInstances.containsKey( id ) )
183 repo = currentInstances.remove( id );
184 getProvider( repo.getType() ).updateManagedInstance( (EditableManagedRepository) repo, repoConfig );
185 updateReferences( repo, repoConfig );
189 repo = newInstance( repoConfig );
191 result.put( id, repo );
192 if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
194 StagingRepositoryFeature stagF = repo.getFeature( StagingRepositoryFeature.class ).get( );
195 if ( stagF.getStagingRepository( ) != null )
197 String stagingId = getStagingId( id );
198 ManagedRepository stagingRepo;
199 if ( currentInstances.containsKey( stagingId ) )
201 stagingRepo = currentInstances.remove( stagingId );
202 managedRepoConfigs.stream( ).filter( cfg -> stagingId.equals( cfg.getId( ) ) ).findFirst( ).ifPresent(
207 getProvider( stagingRepo.getType() ).updateManagedInstance( (EditableManagedRepository) stagingRepo, stagingRepoConfig );
208 updateReferences( stagingRepo, stagingRepoConfig );
210 catch ( RepositoryException e )
212 log.error( "Could not update staging repo {}: {}", stagingId, e.getMessage( ) );
219 stagingRepo = getStagingRepository( repo );
221 if ( stagingRepo != null )
223 result.put( stagingRepo.getId( ), stagingRepo );
230 catch ( Throwable e )
232 log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
233 return new HashMap<>( );
239 public ManagedRepository newInstance( RepositoryType type, String id ) throws RepositoryException
241 log.debug( "Creating repo {}", id );
242 RepositoryProvider provider = getProvider( type );
243 EditableManagedRepository repo;
246 repo = provider.createManagedInstance( id, id );
248 catch ( IOException e )
250 throw new RepositoryException( "Could not create repository '" + id + "': " + e.getMessage( ) );
252 repo.registerEventHandler( RepositoryEvent.ANY, repositoryHandlerManager );
253 updateReferences( repo, null );
254 repo.setLastState( RepositoryState.REFERENCES_SET );
258 private String getStagingId( String repoId )
260 return repoId + StagingRepositoryFeature.STAGING_REPO_POSTFIX;
264 private ManagedRepository getStagingRepository( ManagedRepository baseRepo ) throws RepositoryException
266 ManagedRepository stageRepo = get( getStagingId( baseRepo.getId( ) ) );
267 final RepositoryType type = baseRepo.getType( );
268 if ( stageRepo == null )
270 RepositoryProvider provider = getProvider( type );
271 ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration( baseRepo );
272 stageRepo = provider.createStagingInstance( cfg );
273 if ( stageRepo.supportsFeature( StagingRepositoryFeature.class ) )
275 stageRepo.getFeature( StagingRepositoryFeature.class ).get( ).setStageRepoNeeded( false );
277 updateReferences( stageRepo, cfg );
282 public ArchivaIndexManager getIndexManager( RepositoryType type )
284 return indexManagerFactory.getIndexManager( type );
287 private void createIndexingContext( EditableRepository editableRepo ) throws RepositoryException
289 if ( editableRepo.supportsFeature( IndexCreationFeature.class ) )
291 ArchivaIndexManager idxManager = getIndexManager( editableRepo.getType( ) );
294 editableRepo.setIndexingContext( idxManager.createContext( editableRepo ) );
295 idxManager.updateLocalIndexPath( editableRepo );
297 catch ( IndexCreationFailedException e )
299 throw new RepositoryException( "Could not create index for repository " + editableRepo.getId( ) + ": " + e.getMessage( ), e );
306 public ManagedRepository newInstance( ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
308 RepositoryType type = RepositoryType.valueOf( repositoryConfiguration.getType( ) );
309 RepositoryProvider provider = getProvider( type );
310 if ( provider == null )
312 throw new RepositoryException( "Provider not found for repository type: " + repositoryConfiguration.getType( ) );
314 final ManagedRepository repo = provider.createManagedInstance( repositoryConfiguration );
315 repo.registerEventHandler( RepositoryEvent.ANY, repositoryHandlerManager );
316 updateReferences( repo, null );
317 if ( repo instanceof EditableRepository )
319 ( (EditableRepository) repo ).setLastState( RepositoryState.REFERENCES_SET );
325 protected ManagedRepositoryConfiguration findRepositoryConfiguration( final Configuration configuration, final String id )
327 return configuration.findManagedRepositoryById( id );
331 protected void removeRepositoryConfiguration( final Configuration configuration, final ManagedRepositoryConfiguration repoConfiguration )
333 configuration.removeManagedRepository( repoConfiguration );
337 protected void addRepositoryConfiguration( Configuration configuration, ManagedRepositoryConfiguration repoConfiguration )
339 configuration.addManagedRepository( repoConfiguration );
343 public ManagedRepository put( ManagedRepository repository ) throws RepositoryException
345 final String id = repository.getId( );
346 ManagedRepository originRepo = getRepositories( ).remove( id );
347 if ( originRepo == null && repositoryHandlerManager.isRegisteredId( id ) )
349 throw new RepositoryException( "There exists a repository with id " + id + ". Could not update with managed repository." );
353 if ( originRepo != null && repository != originRepo )
355 deactivateRepository( originRepo );
356 pushEvent( LifecycleEvent.UNREGISTERED, originRepo );
358 RepositoryProvider provider = getProvider( repository.getType( ) );
359 ManagedRepositoryConfiguration newCfg = provider.getManagedConfiguration( repository );
360 getConfigurationHandler( ).getLock( ).writeLock( ).lock( );
363 Configuration configuration = getConfigurationHandler( ).getBaseConfiguration( );
364 updateReferences( repository, newCfg );
365 ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( id );
366 if ( oldCfg != null )
368 configuration.removeManagedRepository( oldCfg );
370 configuration.addManagedRepository( newCfg );
371 getConfigurationHandler( ).save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
372 setLastState( repository, RepositoryState.SAVED );
373 activateRepository( repository );
377 getConfigurationHandler( ).getLock( ).writeLock( ).unlock( );
379 getRepositories( ).put( id, repository );
380 setLastState( repository, RepositoryState.REGISTERED );
383 catch ( Exception e )
385 // Rollback only partly, because repository is closed already
386 if ( originRepo != null )
388 getRepositories( ).put( id, originRepo );
392 getRepositories( ).remove( id );
394 log.error( "Exception during configuration update {}", e.getMessage( ), e );
395 throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ) );
401 public ManagedRepository put( ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
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( );
408 ManagedRepository repo = null;
409 ManagedRepository oldRepository = null;
410 Configuration configuration = null;
413 boolean updated = false;
414 configuration = getConfigurationHandler( ).getBaseConfiguration( );
415 repo = getRepositories( ).get( id );
416 oldRepository = repo == null ? null : clone( repo, id );
419 repo = put( repositoryConfiguration, configuration );
423 setRepositoryDefaults( repositoryConfiguration );
424 provider.updateManagedInstance( (EditableManagedRepository) repo, repositoryConfiguration );
426 pushEvent( LifecycleEvent.UPDATED, repo );
428 registerNewRepository( repositoryConfiguration, repo, configuration, updated );
430 catch ( IndeterminateConfigurationException | RegistryException e )
432 if ( oldRepository != null )
434 ManagedRepositoryConfiguration oldCfg = provider.getManagedConfiguration( oldRepository );
435 provider.updateManagedInstance( (EditableManagedRepository) repo, oldCfg );
436 rollback( configuration, oldRepository, e, oldCfg );
440 getRepositories( ).remove( id );
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( ) );
447 configLock.unlock( );
453 public ManagedRepository put( ManagedRepositoryConfiguration repositoryConfiguration, Configuration configuration ) throws RepositoryException
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 ) )
461 repo = clone( getRepositories( ).get( id ), id );
462 if ( repo instanceof EditableManagedRepository )
464 getProvider( repoType ).updateManagedInstance( (EditableManagedRepository) repo, repositoryConfiguration );
468 throw new RepositoryException( "The repository is not editable " + id );
473 repo = getProvider( repoType ).createManagedInstance( repositoryConfiguration );
474 setLastState( repo, RepositoryState.CREATED );
476 if ( configuration != null )
478 replaceOrAddRepositoryConfig( repositoryConfiguration, configuration );
480 updateReferences( repo, repositoryConfiguration );
481 setLastState( repo, RepositoryState.REFERENCES_SET );
485 @SuppressWarnings( "unused" )
486 private void setRepositoryDefaults( ManagedRepositoryConfiguration repositoryConfiguration )
488 // We do nothing here
492 public ManagedRepository clone( ManagedRepository repo, String id ) throws RepositoryException
494 RepositoryProvider provider = getProvider( repo.getType( ) );
495 ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration( repo );
497 ManagedRepository cloned = provider.createManagedInstance( cfg );
498 cloned.registerEventHandler( RepositoryEvent.ANY, repositoryHandlerManager );
499 setLastState( cloned, RepositoryState.CREATED );
505 public void updateReferences( ManagedRepository repo, ManagedRepositoryConfiguration repositoryConfiguration ) throws RepositoryException
507 log.debug( "Updating references of repo {}", repo.getId( ) );
508 if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
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 )
515 ManagedRepository stageRepo = get( getStagingId( repo.getId( ) ) );
516 if ( stageRepo == null )
518 stageRepo = getStagingRepository( repo );
519 getRepositories( ).put( stageRepo.getId( ), stageRepo );
520 if ( configuration != null )
522 replaceOrAddRepositoryConfig( provider.getManagedConfiguration( stageRepo ), configuration );
524 pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, stageRepo ) );
526 feature.setStagingRepository( stageRepo );
529 if ( repo instanceof EditableManagedRepository )
531 EditableManagedRepository editableRepo = (EditableManagedRepository) repo;
532 if ( repo.getContent( ) == null )
534 editableRepo.setContent( repositoryContentFactory.getManagedRepositoryContent( repo ) );
535 editableRepo.getContent( ).setRepository( editableRepo );
537 log.debug( "Index repo: " + repo.hasIndex( ) );
538 if ( repo.hasIndex( ) && ( repo.getIndexingContext( ) == null || !repo.getIndexingContext( ).isOpen( ) ) )
540 log.debug( "Creating indexing context for {}", repo.getId( ) );
541 createIndexingContext( editableRepo );
544 repo.registerEventHandler( RepositoryEvent.ANY, repositoryHandlerManager );