diff options
author | Martin Stockhammer <martin_s@apache.org> | 2021-06-01 22:46:51 +0200 |
---|---|---|
committer | Martin Stockhammer <martin_s@apache.org> | 2021-06-01 22:46:51 +0200 |
commit | 0ce53483a85b6b7a3a14417434edf56934b474ba (patch) | |
tree | 148acd378bdb456482396cb46c315024840fd807 /archiva-modules/archiva-base | |
parent | ca18ec34d706efa6fdc6ecde6277ba6004e8eb4e (diff) | |
download | archiva-0ce53483a85b6b7a3a14417434edf56934b474ba.tar.gz archiva-0ce53483a85b6b7a3a14417434edf56934b474ba.zip |
Centralizing repository group handling. First part.
Diffstat (limited to 'archiva-modules/archiva-base')
14 files changed, 592 insertions, 232 deletions
diff --git a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ArchivaConfiguration.java b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ArchivaConfiguration.java index 9d8ead089..f23025702 100644 --- a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ArchivaConfiguration.java +++ b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ArchivaConfiguration.java @@ -56,6 +56,20 @@ public interface ArchivaConfiguration throws RegistryException, IndeterminateConfigurationException; /** + * Save any updated configuration. This method allows to add a tag to the thrown event. + * This allows to verify the origin if the caller is the same as the listener. + * + * @param configuration the configuration to save + * @param eventTag the tag to add to the thrown event + * @throws org.apache.archiva.components.registry.RegistryException + * if there is a problem saving the registry data + * @throws IndeterminateConfigurationException + * if the configuration cannot be saved because it was read from two sources + */ + void save( Configuration configuration, String eventTag ) + throws RegistryException, IndeterminateConfigurationException; + + /** * Determines if the configuration in use was as a result of a defaulted configuration. * * @return true if the configuration was created from the default-archiva.xml as opposed diff --git a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ConfigurationEvent.java b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ConfigurationEvent.java index 397c838fa..9639effbe 100644 --- a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ConfigurationEvent.java +++ b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ConfigurationEvent.java @@ -32,9 +32,17 @@ public class ConfigurationEvent private int type; + private String tag; + public ConfigurationEvent( int type ) { this.type = type; + tag = ""; + } + + public ConfigurationEvent(int type, String tag) { + this.type = type; + this.tag = tag; } public int getType() @@ -42,35 +50,33 @@ public class ConfigurationEvent return type; } + public String getTag( ) + { + return tag; + } + + public void setTag( String tag ) + { + this.tag = tag; + } + @Override - public int hashCode() + public boolean equals( Object o ) { - final int prime = 31; - int result = 1; - result = prime * result + type; - return result; + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + ConfigurationEvent that = (ConfigurationEvent) o; + + if ( type != that.type ) return false; + return tag.equals( that.tag ); } @Override - public boolean equals( Object obj ) + public int hashCode( ) { - if ( this == obj ) - { - return true; - } - if ( obj == null ) - { - return false; - } - if ( getClass() != obj.getClass() ) - { - return false; - } - final ConfigurationEvent other = (ConfigurationEvent) obj; - if ( type != other.type ) - { - return false; - } - return true; + int result = type; + result = 31 * result + tag.hashCode( ); + return result; } } diff --git a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/DefaultArchivaConfiguration.java b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/DefaultArchivaConfiguration.java index 11ae70569..ee80fc8fc 100644 --- a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/DefaultArchivaConfiguration.java +++ b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/DefaultArchivaConfiguration.java @@ -410,7 +410,20 @@ public class DefaultArchivaConfiguration @SuppressWarnings("unchecked") @Override - public synchronized void save(Configuration configuration) + public synchronized void save(Configuration configuration) throws IndeterminateConfigurationException, RegistryException + { + save( configuration, "" ); + } + + /** + * Saves the configuration and adds the given tag to the event. + * @param configuration the configuration to save + * @param eventTag the tag to add to the configuration saved event + * @throws IndeterminateConfigurationException if the + * @throws RegistryException + */ + @Override + public synchronized void save(Configuration configuration, String eventTag) throws IndeterminateConfigurationException, RegistryException { Registry section = registry.getSection(KEY + ".user"); Registry baseSection = registry.getSection(KEY + ".base"); @@ -491,7 +504,7 @@ public class DefaultArchivaConfiguration this.configuration = unescapeExpressions(configuration); isConfigurationDefaulted = false; - triggerEvent(ConfigurationEvent.SAVED); + triggerEvent(ConfigurationEvent.SAVED, eventTag); } private void escapeCronExpressions(Configuration configuration) { @@ -530,7 +543,7 @@ public class DefaultArchivaConfiguration addRegistryChangeListener(regListener); } - triggerEvent(ConfigurationEvent.SAVED); + triggerEvent(ConfigurationEvent.SAVED, "default-file"); Registry section = registry.getSection(KEY + ".user"); if (section == null) { @@ -580,8 +593,8 @@ public class DefaultArchivaConfiguration } } - private void triggerEvent(int type) { - ConfigurationEvent evt = new ConfigurationEvent(type); + private void triggerEvent(int type, String eventTag) { + ConfigurationEvent evt = new ConfigurationEvent(type, eventTag); for (ConfigurationListener listener : listeners) { listener.configurationEvent(evt); } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java index f1791b7d0..b2f66aa7f 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java @@ -26,6 +26,7 @@ import org.apache.archiva.metadata.repository.RepositorySessionFactory; import org.apache.archiva.repository.ManagedRepositoryContent; import org.apache.archiva.repository.RepositoryRegistry; import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.repository.maven.metadata.storage.Maven2RepositoryPathTranslator; import org.apache.archiva.repository.base.BasicManagedRepository; import org.apache.archiva.repository.ReleaseScheme; @@ -113,6 +114,10 @@ public abstract class AbstractRepositoryPurgeTest @Inject protected ApplicationContext applicationContext; + @SuppressWarnings( "unused" ) + @Inject + RepositoryGroupHandler repositoryGroupHandler; + @Before public void setUp() diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurgeTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurgeTest.java index 76b6ce72d..8e497dc2c 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurgeTest.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurgeTest.java @@ -74,6 +74,8 @@ public class CleanupReleasedSnapshotsRepositoryPurgeTest @Inject MetadataTools metadataTools; + + @Before @Override public void setUp() diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-indexer-consumers/src/test/java/org/apache/archiva/consumers/lucene/NexusIndexerConsumerTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-indexer-consumers/src/test/java/org/apache/archiva/consumers/lucene/NexusIndexerConsumerTest.java index 85ee9426d..241eeb09b 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-indexer-consumers/src/test/java/org/apache/archiva/consumers/lucene/NexusIndexerConsumerTest.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-indexer-consumers/src/test/java/org/apache/archiva/consumers/lucene/NexusIndexerConsumerTest.java @@ -27,6 +27,7 @@ import org.apache.archiva.components.taskqueue.TaskQueueException; import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; import org.apache.archiva.repository.base.BasicManagedRepository; import org.apache.archiva.repository.ReleaseScheme; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.scheduler.ArchivaTaskScheduler; import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; @@ -96,6 +97,9 @@ public class NexusIndexerConsumerTest @Inject ArchivaRepositoryRegistry repositoryRegistry; + @SuppressWarnings( "unused" ) + @Inject + RepositoryGroupHandler repositoryGroupHandler; @Override @Before diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java index ae6c4fd3b..13f3ce6f9 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/group/DefaultRepositoryGroupAdmin.java @@ -29,11 +29,15 @@ import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; import org.apache.archiva.admin.repository.AbstractRepositoryAdmin; import org.apache.archiva.configuration.Configuration; import org.apache.archiva.configuration.RepositoryGroupConfiguration; +import org.apache.archiva.event.Event; +import org.apache.archiva.event.EventHandler; +import org.apache.archiva.event.EventType; import org.apache.archiva.metadata.model.facets.AuditEvent; import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler; import org.apache.archiva.repository.EditableRepositoryGroup; import org.apache.archiva.repository.RepositoryException; import org.apache.archiva.repository.RepositoryRegistry; +import org.apache.archiva.repository.event.RepositoryRegistryEvent; import org.apache.archiva.repository.features.IndexCreationFeature; import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.lang3.StringUtils; @@ -62,7 +66,7 @@ import java.util.stream.Collectors; @Service("repositoryGroupAdmin#default") public class DefaultRepositoryGroupAdmin extends AbstractRepositoryAdmin - implements RepositoryGroupAdmin + implements RepositoryGroupAdmin, EventHandler<Event> { private Logger log = LoggerFactory.getLogger( getClass() ); @@ -82,6 +86,10 @@ public class DefaultRepositoryGroupAdmin private Path groupsDirectory; @PostConstruct + public void baseInit() { + this.repositoryRegistry.registerEventHandler( EventType.ROOT, this ); + } + public void initialize() { String appServerBase = getRegistry().getString( "appserver.base" ); @@ -438,4 +446,14 @@ public class DefaultRepositoryGroupAdmin rg.setLocation( group.getLocation().toString() ); return rg; } + + @Override + public void handle( Event event ) + { + if ( EventType.isInstanceOf( event.getType( ), RepositoryRegistryEvent.INITIALIZED ) ) + { + log.debug( "Initializing RepositoryGroupAdmin" ); + initialize(); + } + } } diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/AbstractRepositoryAdminTest.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/AbstractRepositoryAdminTest.java index d3086e2f7..993151a83 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/AbstractRepositoryAdminTest.java +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/AbstractRepositoryAdminTest.java @@ -31,6 +31,7 @@ import org.apache.archiva.configuration.ArchivaConfiguration; import org.apache.archiva.redback.role.RoleManager; import org.apache.archiva.redback.users.User; import org.apache.archiva.redback.users.memory.SimpleUser; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.apache.commons.lang3.StringUtils; import org.junit.Before; @@ -84,6 +85,10 @@ public abstract class AbstractRepositoryAdminTest @Inject private ArchivaConfiguration archivaConfiguration; + @SuppressWarnings( "unused" ) + @Inject + RepositoryGroupHandler repositoryGroupHandler; + @Before public void initialize() { Path confFile = Paths.get(APPSERVER_BASE_PATH, "conf/archiva.xml"); diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/group/RepositoryGroupAdminTest.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/group/RepositoryGroupAdminTest.java index ed6e28683..49fd38573 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/group/RepositoryGroupAdminTest.java +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/java/org/apache/archiva/admin/repository/group/RepositoryGroupAdminTest.java @@ -26,6 +26,7 @@ import org.apache.archiva.admin.repository.AbstractRepositoryAdminTest; import org.apache.archiva.metadata.model.facets.AuditEvent; import org.apache.archiva.repository.Repository; import org.apache.archiva.repository.RepositoryRegistry; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.junit.Test; import javax.inject.Inject; @@ -44,6 +45,9 @@ public class RepositoryGroupAdminTest @Inject RepositoryRegistry repositoryRegistry; + @Inject + RepositoryGroupHandler repositoryGroupHandler; + @Test public void addAndDeleteGroup() throws Exception diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/event/RepositoryRegistryEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/event/RepositoryRegistryEvent.java index 1e1157959..7f3b62ddc 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/event/RepositoryRegistryEvent.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/event/RepositoryRegistryEvent.java @@ -47,6 +47,21 @@ public class RepositoryRegistryEvent extends Event */ public static EventType<RepositoryRegistryEvent> INITIALIZED = new EventType(ANY, "REGISTRY.INITIALIZED"); + /** + * When the repository groups are initialized + */ + public static EventType<RepositoryRegistryEvent> GROUPS_INITIALIZED = new EventType(ANY, "REGISTRY.GROUPS_INITIALIZED"); + + /** + * When the managed repositories are initialized + */ + public static EventType<RepositoryRegistryEvent> MANAGED_REPOS_INITIALIZED = new EventType(ANY, "REGISTRY.MANAGED_REPOS_INITIALIZED"); + + /** + * When the remote repositories are initialized + */ + public static EventType<RepositoryRegistryEvent> REMOTE_REPOS_INITIALIZED = new EventType(ANY, "REGISTRY.REMOTE_REPOS_INITIALIZED"); + public RepositoryRegistryEvent(EventType<? extends RepositoryRegistryEvent> type, Object origin) { super(type, origin); } diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java index b909e24de..6a3d0e0b3 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java @@ -28,7 +28,6 @@ import org.apache.archiva.components.registry.RegistryException; import org.apache.archiva.repository.EditableManagedRepository; import org.apache.archiva.repository.EditableRemoteRepository; import org.apache.archiva.repository.EditableRepository; -import org.apache.archiva.repository.EditableRepositoryGroup; import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.RemoteRepository; import org.apache.archiva.repository.Repository; @@ -55,12 +54,11 @@ import javax.annotation.PreDestroy; import javax.inject.Inject; import javax.inject.Named; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH; - /** * Registry for repositories. This is the central entry point for repositories. It provides methods for * retrieving, adding and removing repositories. @@ -78,6 +76,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa { private static final Logger log = LoggerFactory.getLogger(RepositoryRegistry.class); + private final ConfigurationHandler configurationHandler; /** * We inject all repository providers @@ -89,15 +88,14 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa IndexManagerFactory indexManagerFactory; @Inject - ArchivaConfiguration archivaConfiguration; - - @Inject List<MetadataReader> metadataReaderList; @Inject @Named("repositoryContentFactory#default") RepositoryContentFactory repositoryContentFactory; + + private final EventManager eventManager; @@ -107,20 +105,23 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa private Map<String, RemoteRepository> remoteRepositories = new HashMap<>(); private Map<String, RemoteRepository> uRemoteRepositories = Collections.unmodifiableMap(remoteRepositories); - private Map<String, RepositoryGroup> repositoryGroups = new HashMap<>(); - private Map<String, RepositoryGroup> uRepositoryGroups = Collections.unmodifiableMap(repositoryGroups); - private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); - private volatile boolean ignoreConfigEvents = false; + private RepositoryGroupHandler groupHandler; - public ArchivaRepositoryRegistry() { + private AtomicBoolean groups_initalized = new AtomicBoolean( false ); + private AtomicBoolean managed_initialized = new AtomicBoolean( false ); + private AtomicBoolean remote_initialized = new AtomicBoolean( false ); + + + public ArchivaRepositoryRegistry(ConfigurationHandler configurationHandler) { this.eventManager = new EventManager(this); + this.configurationHandler = configurationHandler; } @Override public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration ) { - this.archivaConfiguration = archivaConfiguration; + this.configurationHandler.setArchivaConfiguration( archivaConfiguration ); } @PostConstruct @@ -128,21 +129,41 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa rwLock.writeLock().lock(); try { log.debug("Initializing repository registry"); - updateManagedRepositoriesFromConfig(); - updateRemoteRepositoriesFromConfig(); - - repositoryGroups.clear(); - Map<String, RepositoryGroup> repositoryGroups = getRepositorGroupsFromConfig(); - this.repositoryGroups.putAll(repositoryGroups); - - // archivaConfiguration.addChangeListener(this); - archivaConfiguration.addListener(this); + updateManagedRepositoriesFromConfig( ); + pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.MANAGED_REPOS_INITIALIZED, this ) ); + managed_initialized.set( true ); + updateRemoteRepositoriesFromConfig( ); + pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.REMOTE_REPOS_INITIALIZED, this ) ); + remote_initialized.set( true ); + + initializeRepositoryGroups(); + this.configurationHandler.addListener(this); } finally { rwLock.writeLock().unlock(); } pushEvent(new RepositoryRegistryEvent(RepositoryRegistryEvent.RELOADED, this)); + if (managed_initialized.get() && remote_initialized.get() && groups_initalized.get( )) { + pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) ); + } } + private void initializeRepositoryGroups() { + if (this.groupHandler!=null) { + this.groupHandler.initializeFromConfig(); + this.groups_initalized.set( true ); + pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.GROUPS_INITIALIZED, this ) ); + } + } + + public void registerGroupHandler(RepositoryGroupHandler groupHandler) { + this.groupHandler = groupHandler; + initializeRepositoryGroups(); + if (managed_initialized.get() && remote_initialized.get() && groups_initalized.get( )) { + pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) ); + } + } + + @PreDestroy public void destroy() { for (ManagedRepository rep : managedRepositories.values()) { @@ -153,11 +174,12 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa repo.close(); } remoteRepositories.clear(); + groupHandler.close(); pushEvent(new RepositoryRegistryEvent(RepositoryRegistryEvent.DESTROYED, this)); } - private Map<RepositoryType, RepositoryProvider> createProviderMap() { + protected Map<RepositoryType, RepositoryProvider> getRepositoryProviderMap() { Map<RepositoryType, RepositoryProvider> map = new HashMap<>(); if (repositoryProviders != null) { for (RepositoryProvider provider : repositoryProviders) { @@ -169,7 +191,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa return map; } - private RepositoryProvider getProvider(RepositoryType type) throws RepositoryException + protected RepositoryProvider getProvider(RepositoryType type) throws RepositoryException { return repositoryProviders.stream().filter(repositoryProvider -> repositoryProvider.provides().contains(type)).findFirst().orElseThrow(() -> new RepositoryException("Repository type cannot be handled: " + type)); } @@ -182,7 +204,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa Set<String> configRepoIds = new HashSet<>(); List<ManagedRepositoryConfiguration> managedRepoConfigs = - getArchivaConfiguration().getConfiguration().getManagedRepositories(); + configurationHandler.getBaseConfiguration().getManagedRepositories(); if (managedRepoConfigs == null) { return; @@ -299,7 +321,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa private void updateRemoteRepositoriesFromConfig() { try { List<RemoteRepositoryConfiguration> remoteRepoConfigs = - getArchivaConfiguration().getConfiguration().getRemoteRepositories(); + configurationHandler.getBaseConfiguration().getRemoteRepositories(); if (remoteRepoConfigs == null) { return; @@ -341,53 +363,8 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa repo.registerEventHandler(RepositoryEvent.ANY, this); } - private Map<String, RepositoryGroup> getRepositorGroupsFromConfig() { - try { - List<RepositoryGroupConfiguration> repositoryGroupConfigurations = - getArchivaConfiguration().getConfiguration().getRepositoryGroups(); - - if (repositoryGroupConfigurations == null) { - return Collections.emptyMap(); - } - - Map<String, RepositoryGroup> repositoryGroupMap = new LinkedHashMap<>(repositoryGroupConfigurations.size()); - - Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap(); - for (RepositoryGroupConfiguration repoConfig : repositoryGroupConfigurations) { - RepositoryType repositoryType = RepositoryType.valueOf(repoConfig.getType()); - if (providerMap.containsKey(repositoryType)) { - try { - RepositoryGroup repo = createNewRepositoryGroup(providerMap.get(repositoryType), repoConfig); - repositoryGroupMap.put(repo.getId(), repo); - } catch (Exception e) { - log.error("Could not create repository group {}: {}", repoConfig.getId(), e.getMessage(), e); - } - } - } - return repositoryGroupMap; - } catch (Throwable e) { - log.error("Could not initialize repositories from config: {}", e.getMessage(), e); - return Collections.emptyMap(); - } - } - - private RepositoryGroup createNewRepositoryGroup(RepositoryProvider provider, RepositoryGroupConfiguration config) throws RepositoryException { - RepositoryGroup repositoryGroup = provider.createRepositoryGroup(config); - repositoryGroup.registerEventHandler(RepositoryEvent.ANY, this); - updateRepositoryReferences(provider, repositoryGroup, config); - return repositoryGroup; - } - private void updateRepositoryReferences(RepositoryProvider provider, RepositoryGroup group, RepositoryGroupConfiguration configuration) { - if (group instanceof EditableRepositoryGroup ) { - EditableRepositoryGroup eGroup = (EditableRepositoryGroup) group; - eGroup.setRepositories(configuration.getRepositories().stream().map(r -> getManagedRepository(r)).collect(Collectors.toList())); - } - } - private ArchivaConfiguration getArchivaConfiguration() { - return this.archivaConfiguration; - } /** * Returns all repositories that are registered. There is no defined order of the returned repositories. @@ -438,7 +415,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa public Collection<RepositoryGroup> getRepositoryGroups( ) { rwLock.readLock().lock(); try { - return uRepositoryGroups.values(); + return groupHandler.getRepositoryGroups( ); } finally { rwLock.readLock().unlock(); } @@ -462,8 +439,8 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa } else if (remoteRepositories.containsKey(repoId)) { log.debug("Remote repo"); return remoteRepositories.get(repoId); - } else if (repositoryGroups.containsKey(repoId)) { - return repositoryGroups.get(repoId); + } else if (groupHandler.hasRepositoryGroup(repoId)) { + return groupHandler.getRepositoryGroup(repoId); } else { return null; } @@ -510,23 +487,14 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa public RepositoryGroup getRepositoryGroup( String groupId ) { rwLock.readLock().lock(); try { - return repositoryGroups.get(groupId); + return groupHandler.getRepositoryGroup(groupId); } finally { rwLock.readLock().unlock(); } } - /* - * The <code>ignoreConfigEvents</code> works only for synchronized configuration events. - * If the configuration throws async events, we cannot know, if the event is caused by this instance or another thread. - */ - private void saveConfiguration(Configuration configuration) throws IndeterminateConfigurationException, RegistryException { - ignoreConfigEvents = true; - try { - getArchivaConfiguration().save(configuration); - } finally { - ignoreConfigEvents = false; - } + protected void saveConfiguration(Configuration configuration) throws IndeterminateConfigurationException, RegistryException { + configurationHandler.save(configuration, ConfigurationHandler.REGISTRY_EVENT_TAG ); } /** @@ -552,7 +520,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa } RepositoryProvider provider = getProvider(managedRepository.getType()); ManagedRepositoryConfiguration newCfg = provider.getManagedConfiguration(managedRepository); - Configuration configuration = getArchivaConfiguration().getConfiguration(); + Configuration configuration = configurationHandler.getBaseConfiguration(); updateRepositoryReferences(provider, managedRepository, newCfg, configuration); ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById(id); if (oldCfg != null) { @@ -595,7 +563,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa try { final String id = managedRepositoryConfiguration.getId(); final RepositoryType repositoryType = RepositoryType.valueOf(managedRepositoryConfiguration.getType()); - Configuration configuration = getArchivaConfiguration().getConfiguration(); + Configuration configuration = configurationHandler.getBaseConfiguration(); ManagedRepository repo = managedRepositories.get(id); ManagedRepositoryConfiguration oldCfg = repo != null ? getProvider(repositoryType).getManagedConfiguration(repo) : null; repo = putRepository(managedRepositoryConfiguration, configuration); @@ -670,33 +638,10 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa public RepositoryGroup putRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException { rwLock.writeLock().lock(); try { - final String id = repositoryGroup.getId(); - RepositoryGroup originRepoGroup = repositoryGroups.put(id, repositoryGroup); - try { - if (originRepoGroup != null && originRepoGroup != repositoryGroup) { - originRepoGroup.close(); - } - RepositoryProvider provider = getProvider(repositoryGroup.getType()); - RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration(repositoryGroup); - Configuration configuration = getArchivaConfiguration().getConfiguration(); - updateRepositoryReferences(provider, repositoryGroup, newCfg); - RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById(id); - if (oldCfg != null) { - configuration.removeRepositoryGroup(oldCfg); - } - configuration.addRepositoryGroup(newCfg); - saveConfiguration(configuration); - return repositoryGroup; - } catch (Exception e) { - // Rollback - if (originRepoGroup != null) { - repositoryGroups.put(id, originRepoGroup); - } else { - repositoryGroups.remove(id); - } - log.error("Exception during configuration update {}", e.getMessage(), e); - throw new RepositoryException("Could not save the configuration" + (e.getMessage() == null ? "" : ": " + e.getMessage())); + if (this.groupHandler==null) { + throw new RepositoryException( "Fatal error. RepositoryGroupHandler not registered!" ); } + return this.groupHandler.putRepositoryGroup( repositoryGroup ); } finally { rwLock.writeLock().unlock(); } @@ -714,22 +659,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException { rwLock.writeLock().lock(); try { - final String id = repositoryGroupConfiguration.getId(); - final RepositoryType repositoryType = RepositoryType.valueOf(repositoryGroupConfiguration.getType()); - Configuration configuration = getArchivaConfiguration().getConfiguration(); - RepositoryGroup repo = repositoryGroups.get(id); - RepositoryGroupConfiguration oldCfg = repo != null ? getProvider(repositoryType).getRepositoryGroupConfiguration(repo) : null; - repo = putRepositoryGroup(repositoryGroupConfiguration, configuration); - try { - saveConfiguration(configuration); - } catch (IndeterminateConfigurationException | RegistryException e) { - if (oldCfg != null) { - getProvider(repositoryType).updateRepositoryGroupInstance((EditableRepositoryGroup) repo, oldCfg); - } - log.error("Could not save the configuration for repository group {}: {}", id, e.getMessage(), e); - throw new RepositoryException("Could not save the configuration for repository group " + id + ": " + e.getMessage()); - } - return repo; + return groupHandler.putRepositoryGroup( repositoryGroupConfiguration ); } finally { rwLock.writeLock().unlock(); } @@ -749,41 +679,12 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException { rwLock.writeLock().lock(); try { - final String id = repositoryGroupConfiguration.getId(); - final RepositoryType repoType = RepositoryType.valueOf(repositoryGroupConfiguration.getType()); - RepositoryGroup repo; - setRepositoryGroupDefaults(repositoryGroupConfiguration); - if (repositoryGroups.containsKey(id)) { - repo = repositoryGroups.get(id); - if (repo instanceof EditableRepositoryGroup) { - getProvider(repoType).updateRepositoryGroupInstance((EditableRepositoryGroup) repo, repositoryGroupConfiguration); - } else { - throw new RepositoryException("The repository is not editable " + id); - } - } else { - repo = getProvider(repoType).createRepositoryGroup(repositoryGroupConfiguration); - repositoryGroups.put(id, repo); - } - updateRepositoryReferences(getProvider(repoType), repo, repositoryGroupConfiguration); - replaceOrAddRepositoryConfig(repositoryGroupConfiguration, configuration); - return repo; + return groupHandler.putRepositoryGroup( repositoryGroupConfiguration, configuration ); } finally { rwLock.writeLock().unlock(); } } - private void setRepositoryGroupDefaults(RepositoryGroupConfiguration repositoryGroupConfiguration) { - if (StringUtils.isEmpty(repositoryGroupConfiguration.getMergedIndexPath())) { - repositoryGroupConfiguration.setMergedIndexPath(DEFAULT_INDEX_PATH); - } - if (repositoryGroupConfiguration.getMergedIndexTtl() <= 0) { - repositoryGroupConfiguration.setMergedIndexTtl(300); - } - if (StringUtils.isEmpty(repositoryGroupConfiguration.getCronExpression())) { - repositoryGroupConfiguration.setCronExpression("0 0 03 ? * MON"); - } - } - private void replaceOrAddRepositoryConfig(ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration) { if (configuration != null) { ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById(managedRepositoryConfiguration.getId()); @@ -874,7 +775,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa public RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException { rwLock.writeLock().lock(); try { - Configuration configuration = getArchivaConfiguration().getConfiguration(); + Configuration configuration = configurationHandler.getBaseConfiguration(); try { RemoteRepository repo = putRepository(remoteRepository, configuration); saveConfiguration(configuration); @@ -902,7 +803,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa try { final String id = remoteRepositoryConfiguration.getId(); final RepositoryType repositoryType = RepositoryType.valueOf(remoteRepositoryConfiguration.getType()); - Configuration configuration = getArchivaConfiguration().getConfiguration(); + Configuration configuration = configurationHandler.getBaseConfiguration(); RemoteRepository repo = remoteRepositories.get(id); RemoteRepositoryConfiguration oldCfg = repo != null ? getProvider(repositoryType).getRemoteConfiguration(repo) : null; repo = putRepository(remoteRepositoryConfiguration, configuration); @@ -1012,8 +913,8 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa repo = managedRepositories.remove(id); if (repo != null) { repo.close(); - removeRepositoryFromGroups(repo); - Configuration configuration = getArchivaConfiguration().getConfiguration(); + this.groupHandler.removeRepositoryFromGroups(repo); + Configuration configuration = configurationHandler.getBaseConfiguration(); ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById(id); if (cfg != null) { configuration.removeManagedRepository(cfg); @@ -1032,12 +933,6 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa } } - private void removeRepositoryFromGroups(ManagedRepository repo) { - if (repo != null) { - repositoryGroups.values().stream().filter(repoGroup -> repoGroup instanceof EditableRepository). - map(repoGroup -> (EditableRepositoryGroup) repoGroup).forEach(repoGroup -> repoGroup.removeRepository(repo)); - } - } @Override public void removeRepository( ManagedRepository managedRepository, Configuration configuration ) throws RepositoryException { @@ -1052,7 +947,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa repo = managedRepositories.remove(id); if (repo != null) { repo.close(); - removeRepositoryFromGroups(repo); + this.groupHandler.removeRepositoryFromGroups(repo); ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById(id); if (cfg != null) { configuration.removeManagedRepository(cfg); @@ -1080,26 +975,10 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa return; } final String id = repositoryGroup.getId(); - RepositoryGroup repo = getRepositoryGroup(id); - if (repo != null) { + if (groupHandler.hasRepositoryGroup( id )) { rwLock.writeLock().lock(); try { - repo = repositoryGroups.remove(id); - if (repo != null) { - repo.close(); - Configuration configuration = getArchivaConfiguration().getConfiguration(); - RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById(id); - if (cfg != null) { - configuration.removeRepositoryGroup(cfg); - } - saveConfiguration(configuration); - } - - } catch (RegistryException | IndeterminateConfigurationException e) { - // Rollback - log.error("Could not save config after repository removal: {}", e.getMessage(), e); - repositoryGroups.put(repo.getId(), repo); - throw new RepositoryException("Could not save configuration after repository removal: " + e.getMessage()); + groupHandler.removeRepositoryGroup( id ); } finally { rwLock.writeLock().unlock(); } @@ -1112,23 +991,14 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa return; } final String id = repositoryGroup.getId(); - RepositoryGroup repo = getRepositoryGroup(id); - if (repo != null) { + if (groupHandler.hasRepositoryGroup( id )) { rwLock.writeLock().lock(); try { - repo = repositoryGroups.remove(id); - if (repo != null) { - repo.close(); - RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById(id); - if (cfg != null) { - configuration.removeRepositoryGroup(cfg); - } - } + groupHandler.removeRepositoryGroup( id, configuration ); } finally { rwLock.writeLock().unlock(); } } - } private void doRemoveRepo(RemoteRepository repo, Configuration configuration) { @@ -1164,7 +1034,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa try { repo = remoteRepositories.remove(id); if (repo != null) { - Configuration configuration = getArchivaConfiguration().getConfiguration(); + Configuration configuration = configurationHandler.getBaseConfiguration(); doRemoveRepo(repo, configuration); saveConfiguration(configuration); } @@ -1292,8 +1162,9 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa @Override public void configurationEvent(ConfigurationEvent event) { - // Note: the ignoreConfigEvents flag does not work, if the config events are asynchronous. - if (!ignoreConfigEvents) { + // We ignore the event, if the save was triggered by ourself + if ( !ConfigurationHandler.REGISTRY_EVENT_TAG.equals( event.getTag( ) ) ) + { reload(); } } diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ConfigurationHandler.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ConfigurationHandler.java new file mode 100644 index 000000000..c4ee51370 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ConfigurationHandler.java @@ -0,0 +1,71 @@ +package org.apache.archiva.repository.base; +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.archiva.components.registry.RegistryException; +import org.apache.archiva.configuration.ArchivaConfiguration; +import org.apache.archiva.configuration.Configuration; +import org.apache.archiva.configuration.ConfigurationListener; +import org.apache.archiva.configuration.IndeterminateConfigurationException; +import org.springframework.stereotype.Service; + +/** + * This is just a simple wrapper to access the archiva configuration used by the registry and associated classes + * + * @author Martin Stockhammer <martin_s@apache.org> + */ +@Service("configurationHandler#default") +public class ConfigurationHandler +{ + public static final String REGISTRY_EVENT_TAG = "repositoryRegistry"; + + private ArchivaConfiguration archivaConfiguration; + + public ConfigurationHandler( ArchivaConfiguration archivaConfiguration ) { + this.archivaConfiguration = archivaConfiguration; + } + + public void addListener( ConfigurationListener listener ) { + this.archivaConfiguration.addListener( listener ); + } + + public ArchivaConfiguration getArchivaConfiguration( ) + { + return archivaConfiguration; + } + + public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration ) + { + this.archivaConfiguration = archivaConfiguration; + } + + public Configuration getBaseConfiguration() { + return archivaConfiguration.getConfiguration( ); + } + + public void save(Configuration configuration, String eventTag) throws IndeterminateConfigurationException, RegistryException + { + archivaConfiguration.save( configuration, eventTag); + } + + public void save(Configuration configuration) throws IndeterminateConfigurationException, RegistryException + { + archivaConfiguration.save( configuration, "" ); + } + +} diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/RepositoryGroupHandler.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/RepositoryGroupHandler.java new file mode 100644 index 000000000..f4b02a2d6 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/RepositoryGroupHandler.java @@ -0,0 +1,328 @@ +package org.apache.archiva.repository.base; +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.archiva.components.registry.RegistryException; +import org.apache.archiva.configuration.Configuration; +import org.apache.archiva.configuration.IndeterminateConfigurationException; +import org.apache.archiva.configuration.RepositoryGroupConfiguration; +import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler; +import org.apache.archiva.repository.EditableRepository; +import org.apache.archiva.repository.EditableRepositoryGroup; +import org.apache.archiva.repository.ManagedRepository; +import org.apache.archiva.repository.RepositoryException; +import org.apache.archiva.repository.RepositoryGroup; +import org.apache.archiva.repository.RepositoryProvider; +import org.apache.archiva.repository.RepositoryType; +import org.apache.archiva.repository.event.RepositoryEvent; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.inject.Named; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH; + +/** + * This class manages repository groups for the RepositoryRegistry. + * It is tightly coupled with the {@link ArchivaRepositoryRegistry}. + * + * @author Martin Stockhammer <martin_s@apache.org> + */ +@Service("repositoryGroupHandler#default") +public class RepositoryGroupHandler +{ + private static final Logger log = LoggerFactory.getLogger(RepositoryGroupHandler.class); + + private final ArchivaRepositoryRegistry repositoryRegistry; + private final ConfigurationHandler configurationHandler; + private final MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler; + + private Map<String, RepositoryGroup> repositoryGroups = new HashMap<>(); + + /** + * Creates a new instance. All dependencies are injected on the constructor. + * @param repositoryRegistry the registry. To avoid circular dependencies via DI, this class registers itself on the registry. + * @param configurationHandler the configuration handler is used to retrieve and save configuration. + * @param mergedRemoteIndexesScheduler the index scheduler is used for merging the indexes from all group members + */ + public RepositoryGroupHandler( ArchivaRepositoryRegistry repositoryRegistry, + ConfigurationHandler configurationHandler, + @Named("mergedRemoteIndexesScheduler#default") MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler) { + this.configurationHandler = configurationHandler; + this.mergedRemoteIndexesScheduler = mergedRemoteIndexesScheduler; + this.repositoryRegistry = repositoryRegistry; + } + + @PostConstruct + private void init() { + log.debug( "Initializing repository group handler " + repositoryRegistry.toString( ) ); + // We are registering this class on the registry. This is necessary to avoid circular dependencies via injection. + this.repositoryRegistry.registerGroupHandler( this ); + } + + public void initializeFromConfig() { + this.repositoryGroups.clear(); + this.repositoryGroups.putAll( getRepositorGroupsFromConfig( ) ); + } + + public Map<String, RepositoryGroup> getRepositorGroupsFromConfig() { + try { + List<RepositoryGroupConfiguration> repositoryGroupConfigurations = + this.configurationHandler.getBaseConfiguration().getRepositoryGroups(); + + if (repositoryGroupConfigurations == null) { + return Collections.emptyMap(); + } + + Map<String, RepositoryGroup> repositoryGroupMap = new LinkedHashMap<>(repositoryGroupConfigurations.size()); + + Map<RepositoryType, RepositoryProvider> providerMap = repositoryRegistry.getRepositoryProviderMap(); + for (RepositoryGroupConfiguration repoConfig : repositoryGroupConfigurations) { + RepositoryType repositoryType = RepositoryType.valueOf(repoConfig.getType()); + if (providerMap.containsKey(repositoryType)) { + try { + RepositoryGroup repo = createNewRepositoryGroup(providerMap.get(repositoryType), repoConfig); + repositoryGroupMap.put(repo.getId(), repo); + } catch (Exception e) { + log.error("Could not create repository group {}: {}", repoConfig.getId(), e.getMessage(), e); + } + } + } + return repositoryGroupMap; + } catch (Throwable e) { + log.error("Could not initialize repositories from config: {}", e.getMessage(), e); + return Collections.emptyMap(); + } + } + + public RepositoryGroup createNewRepositoryGroup(RepositoryProvider provider, RepositoryGroupConfiguration config) throws RepositoryException + { + RepositoryGroup repositoryGroup = provider.createRepositoryGroup(config); + repositoryGroup.registerEventHandler( RepositoryEvent.ANY, repositoryRegistry); + updateRepositoryReferences(provider, repositoryGroup, config); + return repositoryGroup; + } + + public void updateRepositoryReferences( RepositoryProvider provider, RepositoryGroup group, RepositoryGroupConfiguration configuration) { + if (group instanceof EditableRepositoryGroup ) { + EditableRepositoryGroup eGroup = (EditableRepositoryGroup) group; + eGroup.setRepositories(configuration.getRepositories().stream() + .map(r -> repositoryRegistry.getManagedRepository(r)).collect( Collectors.toList())); + } + } + + /** + * Adds a new repository group to the current list, or replaces the repository group definition with + * the same id, if it exists already. + * The change is saved to the configuration immediately. + * + * @param repositoryGroup the new repository group. + * @throws RepositoryException if the new repository group could not be saved to the configuration. + */ + public RepositoryGroup putRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException { + final String id = repositoryGroup.getId(); + RepositoryGroup originRepoGroup = repositoryGroups.put(id, repositoryGroup); + try { + if (originRepoGroup != null && originRepoGroup != repositoryGroup) { + originRepoGroup.close(); + } + RepositoryProvider provider = repositoryRegistry.getProvider( repositoryGroup.getType()); + RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration(repositoryGroup); + Configuration configuration = this.configurationHandler.getBaseConfiguration(); + updateRepositoryReferences(provider, repositoryGroup, newCfg); + RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById(id); + if (oldCfg != null) { + configuration.removeRepositoryGroup(oldCfg); + } + configuration.addRepositoryGroup(newCfg); + repositoryRegistry.saveConfiguration(configuration); + return repositoryGroup; + } catch (Exception e) { + // Rollback + if (originRepoGroup != null) { + repositoryGroups.put(id, originRepoGroup); + } else { + repositoryGroups.remove(id); + } + log.error("Exception during configuration update {}", e.getMessage(), e); + throw new RepositoryException("Could not save the configuration" + (e.getMessage() == null ? "" : ": " + e.getMessage())); + } + } + + /** + * Adds a new repository group or updates the repository with the same id, if it exists already. + * The configuration is saved immediately. + * + * @param repositoryGroupConfiguration the repository configuration + * @return the updated or created repository + * @throws RepositoryException if an error occurs, or the configuration is not valid. + */ + public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException { + final String id = repositoryGroupConfiguration.getId(); + final RepositoryType repositoryType = RepositoryType.valueOf(repositoryGroupConfiguration.getType()); + Configuration configuration = this.configurationHandler.getBaseConfiguration(); + RepositoryGroup repo = repositoryGroups.get(id); + RepositoryGroupConfiguration oldCfg = repo != null ? repositoryRegistry.getProvider(repositoryType).getRepositoryGroupConfiguration(repo) : null; + repo = putRepositoryGroup(repositoryGroupConfiguration, configuration); + try { + repositoryRegistry.saveConfiguration(configuration); + } catch ( IndeterminateConfigurationException | RegistryException e) { + if (oldCfg != null) { + repositoryRegistry.getProvider(repositoryType).updateRepositoryGroupInstance((EditableRepositoryGroup) repo, oldCfg); + } + log.error("Could not save the configuration for repository group {}: {}", id, e.getMessage(), e); + throw new RepositoryException("Could not save the configuration for repository group " + id + ": " + e.getMessage()); + } + return repo; + } + + public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException { + final String id = repositoryGroupConfiguration.getId(); + final RepositoryType repoType = RepositoryType.valueOf(repositoryGroupConfiguration.getType()); + RepositoryGroup repo; + setRepositoryGroupDefaults(repositoryGroupConfiguration); + if (repositoryGroups.containsKey(id)) { + repo = repositoryGroups.get(id); + if (repo instanceof EditableRepositoryGroup) { + repositoryRegistry.getProvider(repoType).updateRepositoryGroupInstance((EditableRepositoryGroup) repo, repositoryGroupConfiguration); + } else { + throw new RepositoryException("The repository is not editable " + id); + } + } else { + repo = repositoryRegistry.getProvider(repoType).createRepositoryGroup(repositoryGroupConfiguration); + repositoryGroups.put(id, repo); + } + updateRepositoryReferences(repositoryRegistry.getProvider(repoType), repo, repositoryGroupConfiguration); + replaceOrAddRepositoryConfig(repositoryGroupConfiguration, configuration); + return repo; + } + + private void setRepositoryGroupDefaults(RepositoryGroupConfiguration repositoryGroupConfiguration) { + if ( StringUtils.isEmpty(repositoryGroupConfiguration.getMergedIndexPath())) { + repositoryGroupConfiguration.setMergedIndexPath(DEFAULT_INDEX_PATH); + } + if (repositoryGroupConfiguration.getMergedIndexTtl() <= 0) { + repositoryGroupConfiguration.setMergedIndexTtl(300); + } + if (StringUtils.isEmpty(repositoryGroupConfiguration.getCronExpression())) { + repositoryGroupConfiguration.setCronExpression("0 0 03 ? * MON"); + } + } + + private void replaceOrAddRepositoryConfig(RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration) { + RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById(repositoryGroupConfiguration.getId()); + if (oldCfg != null) { + configuration.removeRepositoryGroup(oldCfg); + } + configuration.addRepositoryGroup(repositoryGroupConfiguration); + } + + public void removeRepositoryFromGroups( ManagedRepository repo) { + if (repo != null) { + repositoryGroups.values().stream().filter(repoGroup -> repoGroup instanceof EditableRepository ). + map(repoGroup -> (EditableRepositoryGroup) repoGroup).forEach(repoGroup -> repoGroup.removeRepository(repo)); + } + } + + /** + * Removes a repository group from the registry and configuration, if it exists. + * The change is saved to the configuration immediately. + * + * @param id the id of the repository group to remove + * @throws RepositoryException if a error occurs during configuration save + */ + public void removeRepositoryGroup( final String id ) throws RepositoryException { + RepositoryGroup repo = getRepositoryGroup(id); + if (repo != null) { + try { + repo = repositoryGroups.remove(id); + if (repo != null) { + repo.close(); + Configuration configuration = this.configurationHandler.getBaseConfiguration(); + RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById(id); + if (cfg != null) { + configuration.removeRepositoryGroup(cfg); + } + this.configurationHandler.save(configuration, ConfigurationHandler.REGISTRY_EVENT_TAG ); + } + + } catch (RegistryException | IndeterminateConfigurationException e) { + // Rollback + log.error("Could not save config after repository removal: {}", e.getMessage(), e); + repositoryGroups.put(repo.getId(), repo); + throw new RepositoryException("Could not save configuration after repository removal: " + e.getMessage()); + } + } + } + + public void removeRepositoryGroup( String id, Configuration configuration ) throws RepositoryException { + RepositoryGroup repo = repositoryGroups.get(id); + if (repo != null) { + repo = repositoryGroups.remove(id); + if (repo != null) { + repo.close(); + RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById(id); + if (cfg != null) { + configuration.removeRepositoryGroup(cfg); + } + } + } + + } + + public RepositoryGroup getRepositoryGroup( String groupId ) { + return repositoryGroups.get(groupId); + } + + public Collection<RepositoryGroup> getRepositoryGroups() { + return repositoryGroups.values( ); + } + + public boolean hasRepositoryGroup(String id) { + return repositoryGroups.containsKey( id ); + } + + @PreDestroy + private void destroy() { + this.close( ); + } + + public void close() { + for (RepositoryGroup group : repositoryGroups.values()) { + try + { + group.close( ); + } catch (Throwable e) { + log.error( "Could not close repository group {}: {}", group.getId( ), e.getMessage( ) ); + } + } + this.repositoryGroups.clear(); + } + +} diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistryTest.java b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistryTest.java index 58965ed18..b7cbf1fb5 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistryTest.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistryTest.java @@ -66,6 +66,10 @@ public class ArchivaRepositoryRegistryTest @Inject ArchivaConfiguration archivaConfiguration; + @SuppressWarnings( "unused" ) + @Inject + RepositoryGroupHandler repositoryGroupHandler; + private static final Path userCfg = Paths.get(System.getProperty( "user.home" ), ".m2/archiva.xml"); private static Path cfgCopy; |