From 0ce53483a85b6b7a3a14417434edf56934b474ba Mon Sep 17 00:00:00 2001 From: Martin Stockhammer Date: Tue, 1 Jun 2021 22:46:51 +0200 Subject: [PATCH] Centralizing repository group handling. First part. --- .../configuration/ArchivaConfiguration.java | 14 + .../configuration/ConfigurationEvent.java | 54 +-- .../DefaultArchivaConfiguration.java | 23 +- .../AbstractRepositoryPurgeTest.java | 5 + ...pReleasedSnapshotsRepositoryPurgeTest.java | 2 + .../lucene/NexusIndexerConsumerTest.java | 4 + .../group/DefaultRepositoryGroupAdmin.java | 20 +- .../AbstractRepositoryAdminTest.java | 5 + .../group/RepositoryGroupAdminTest.java | 4 + .../event/RepositoryRegistryEvent.java | 15 + .../base/ArchivaRepositoryRegistry.java | 275 ++++----------- .../repository/base/ConfigurationHandler.java | 71 ++++ .../base/RepositoryGroupHandler.java | 328 ++++++++++++++++++ .../base/ArchivaRepositoryRegistryTest.java | 4 + .../indexer/maven/MavenIndexManagerTest.java | 4 + .../search/AbstractMavenRepositorySearch.java | 11 +- .../search/MavenRepositorySearchOSGITest.java | 4 + .../MavenRepositorySearchPaginateTest.java | 7 +- .../archiva/proxy/MockConfiguration.java | 6 + .../storage/mock/MockConfiguration.java | 7 + .../maven/mock/RepositoryRegistryMock.java | 6 + .../mock/configuration/StubConfiguration.java | 6 + .../mock/configuration/TestConfiguration.java | 6 + .../ArchivaIndexingTaskExecutorTest.java | 4 + ...ivaRepositoryScanningTaskExecutorTest.java | 4 + .../services/v2/RepositoryGroupService.java | 92 ++--- .../MavenManagedRepositoryService.java | 6 +- .../services/DefaultRepositoriesService.java | 5 + .../rest/services/utils/AuditHelper.java | 40 +++ .../DefaultMavenManagedRepositoryService.java | 25 +- .../v2/DefaultRepositoryGroupService.java | 28 +- .../resources/META-INF/spring-context.xml | 8 +- .../v2/AbstractNativeRestServices.java | 16 +- ...tiveMavenManagedRepositoryServiceTest.java | 97 ++++++ .../META-INF/spring-context-test.xml | 2 +- .../AbstractRepositoryServletTestCase.java | 4 + .../webdav/ArchivaDavResourceFactoryTest.java | 10 +- .../webdav/RepositoryServletSecurityTest.java | 5 + 38 files changed, 897 insertions(+), 330 deletions(-) create mode 100644 archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ConfigurationHandler.java create mode 100644 archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/RepositoryGroupHandler.java rename archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/{ => maven}/MavenManagedRepositoryService.java (98%) create mode 100644 archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/utils/AuditHelper.java create mode 100644 archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeMavenManagedRepositoryServiceTest.java 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 @@ -55,6 +55,20 @@ public interface ArchivaConfiguration void save( Configuration configuration ) 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. * 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 { 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 INITIALIZED = new EventType(ANY, "REGISTRY.INITIALIZED"); + /** + * When the repository groups are initialized + */ + public static EventType GROUPS_INITIALIZED = new EventType(ANY, "REGISTRY.GROUPS_INITIALIZED"); + + /** + * When the managed repositories are initialized + */ + public static EventType MANAGED_REPOS_INITIALIZED = new EventType(ANY, "REGISTRY.MANAGED_REPOS_INITIALIZED"); + + /** + * When the remote repositories are initialized + */ + public static EventType REMOTE_REPOS_INITIALIZED = new EventType(ANY, "REGISTRY.REMOTE_REPOS_INITIALIZED"); + public RepositoryRegistryEvent(EventType 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 @@ -88,9 +87,6 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa @Inject IndexManagerFactory indexManagerFactory; - @Inject - ArchivaConfiguration archivaConfiguration; - @Inject List metadataReaderList; @@ -98,6 +94,8 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa @Named("repositoryContentFactory#default") RepositoryContentFactory repositoryContentFactory; + + private final EventManager eventManager; @@ -107,20 +105,23 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa private Map remoteRepositories = new HashMap<>(); private Map uRemoteRepositories = Collections.unmodifiableMap(remoteRepositories); - private Map repositoryGroups = new HashMap<>(); - private Map 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 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 createProviderMap() { + protected Map getRepositoryProviderMap() { Map 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 configRepoIds = new HashSet<>(); List 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 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 getRepositorGroupsFromConfig() { - try { - List repositoryGroupConfigurations = - getArchivaConfiguration().getConfiguration().getRepositoryGroups(); - - if (repositoryGroupConfigurations == null) { - return Collections.emptyMap(); - } - - Map repositoryGroupMap = new LinkedHashMap<>(repositoryGroupConfigurations.size()); - - Map 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 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 ignoreConfigEvents 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 + */ +@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 + */ +@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 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 getRepositorGroupsFromConfig() { + try { + List repositoryGroupConfigurations = + this.configurationHandler.getBaseConfiguration().getRepositoryGroups(); + + if (repositoryGroupConfigurations == null) { + return Collections.emptyMap(); + } + + Map repositoryGroupMap = new LinkedHashMap<>(repositoryGroupConfigurations.size()); + + Map 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 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; diff --git a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/MavenIndexManagerTest.java b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/MavenIndexManagerTest.java index c025180ed..e8fc6ce1a 100644 --- a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/MavenIndexManagerTest.java +++ b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/MavenIndexManagerTest.java @@ -24,6 +24,7 @@ import org.apache.archiva.indexer.ArchivaIndexingContext; import org.apache.archiva.indexer.IndexCreationFailedException; import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; import org.apache.archiva.repository.RepositoryType; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.repository.features.IndexCreationFeature; import org.apache.archiva.repository.features.RemoteIndexFeature; import org.apache.archiva.repository.maven.MavenManagedRepository; @@ -61,6 +62,9 @@ public class MavenIndexManagerTest { @Inject ArchivaRepositoryRegistry repositoryRegistry; + @Inject + RepositoryGroupHandler groupHandler; + private Path indexPath; private MavenManagedRepository repository; diff --git a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/AbstractMavenRepositorySearch.java b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/AbstractMavenRepositorySearch.java index b94e6b8e5..575d078ad 100644 --- a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/AbstractMavenRepositorySearch.java +++ b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/AbstractMavenRepositorySearch.java @@ -31,6 +31,8 @@ import org.apache.archiva.indexer.search.SearchResults; import org.apache.archiva.proxy.ProxyRegistry; import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; import org.apache.archiva.repository.Repository; +import org.apache.archiva.repository.base.ConfigurationHandler; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.repository.features.IndexCreationFeature; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.apache.commons.lang3.SystemUtils; @@ -92,6 +94,9 @@ public abstract class AbstractMavenRepositorySearch @Inject ArchivaRepositoryRegistry repositoryRegistry; + @Inject + RepositoryGroupHandler repositoryGroupHandler; + @Inject ProxyRegistry proxyRegistry; @@ -143,7 +148,7 @@ public abstract class AbstractMavenRepositorySearch archivaConfig.addListener( EasyMock.anyObject( ConfigurationListener.class ) ); EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes(); EasyMock.expect( archivaConfig.getConfiguration() ).andReturn(config).anyTimes(); - archivaConfig.save(EasyMock.anyObject(Configuration.class)); + archivaConfig.save(EasyMock.anyObject(Configuration.class), EasyMock.anyString()); EasyMock.expectLastCall().anyTimes(); archivaConfigControl.replay(); repositoryRegistry.reload(); @@ -158,7 +163,7 @@ public abstract class AbstractMavenRepositorySearch archivaConfigControl.reset(); EasyMock.expect( archivaConfig.getDefaultLocale() ).andReturn( Locale.getDefault( ) ).anyTimes(); EasyMock.expect( archivaConfig.getConfiguration() ).andReturn(config).anyTimes(); - archivaConfig.save(EasyMock.anyObject(Configuration.class)); + archivaConfig.save(EasyMock.anyObject(Configuration.class), EasyMock.anyString()); EasyMock.expectLastCall().anyTimes(); archivaConfigControl.replay(); repositoryRegistry.removeRepository(TEST_REPO_1); @@ -259,7 +264,7 @@ public abstract class AbstractMavenRepositorySearch archivaConfigControl.reset(); archivaConfig.addListener( EasyMock.anyObject( ConfigurationListener.class ) ); EasyMock.expect( archivaConfig.getConfiguration() ).andReturn(config).anyTimes(); - archivaConfig.save(EasyMock.anyObject(Configuration.class)); + archivaConfig.save(EasyMock.anyObject(Configuration.class), EasyMock.anyString()); EasyMock.expectLastCall().anyTimes(); archivaConfigControl.replay(); repositoryRegistry.reload(); diff --git a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchOSGITest.java b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchOSGITest.java index 8fe10eaf7..90093edf0 100644 --- a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchOSGITest.java +++ b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchOSGITest.java @@ -23,6 +23,7 @@ import org.apache.archiva.indexer.search.SearchFields; import org.apache.archiva.indexer.search.SearchResultHit; import org.apache.archiva.indexer.search.SearchResults; import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.easymock.EasyMock; import org.junit.After; import org.junit.Test; @@ -43,6 +44,9 @@ public class MavenRepositorySearchOSGITest @Inject ArchivaRepositoryRegistry repositoryRegistry; + @Inject + RepositoryGroupHandler repositoryGroupHandler; + @After @Override public void tearDown() throws Exception { diff --git a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchPaginateTest.java b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchPaginateTest.java index 72cc69fc9..f1aa3eb9b 100644 --- a/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchPaginateTest.java +++ b/archiva-modules/archiva-maven/archiva-maven-indexer/src/test/java/org/apache/archiva/indexer/maven/search/MavenRepositorySearchPaginateTest.java @@ -24,6 +24,7 @@ import org.apache.archiva.indexer.search.SearchResultLimits; import org.apache.archiva.indexer.search.SearchResults; import org.apache.archiva.indexer.util.SearchUtil; import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.junit.After; import org.junit.Test; @@ -31,6 +32,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; +import javax.inject.Inject; import java.util.Arrays; /** @@ -42,9 +44,12 @@ public class MavenRepositorySearchPaginateTest extends TestCase { - @Autowired + @Inject ArchivaRepositoryRegistry repositoryRegistry; + @Inject + RepositoryGroupHandler repositoryGroupHandler; + @After public void endTests() { assert repositoryRegistry!=null; diff --git a/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/MockConfiguration.java b/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/MockConfiguration.java index 7e3d945fa..fb9fe0b87 100644 --- a/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/MockConfiguration.java +++ b/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/proxy/MockConfiguration.java @@ -111,6 +111,12 @@ public class MockConfiguration /* do nothing */ } + @Override + public void save( Configuration configuration, String eventTag ) throws RegistryException, IndeterminateConfigurationException + { + // do nothing + } + public void triggerChange( String name, String value ) { for ( org.apache.archiva.components.registry.RegistryListener listener : registryListeners ) diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/metadata/storage/mock/MockConfiguration.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/metadata/storage/mock/MockConfiguration.java index 018f85eac..7085e96a4 100644 --- a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/metadata/storage/mock/MockConfiguration.java +++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/metadata/storage/mock/MockConfiguration.java @@ -27,6 +27,7 @@ import org.apache.archiva.configuration.ArchivaRuntimeConfiguration; import org.apache.archiva.configuration.Configuration; import org.apache.archiva.configuration.ConfigurationListener; import org.apache.archiva.configuration.FileType; +import org.apache.archiva.configuration.IndeterminateConfigurationException; import org.apache.archiva.configuration.RepositoryScanningConfiguration; import org.apache.commons.lang3.StringUtils; import org.easymock.IMocksControl; @@ -109,6 +110,12 @@ public class MockConfiguration /* do nothing */ } + @Override + public void save( Configuration configuration, String eventTag ) throws RegistryException, IndeterminateConfigurationException + { + // do nothing + } + public void triggerChange( String name, String value ) { for(RegistryListener listener: registryListeners) diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/RepositoryRegistryMock.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/RepositoryRegistryMock.java index 9966d8bb1..4ceed3865 100644 --- a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/RepositoryRegistryMock.java +++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/RepositoryRegistryMock.java @@ -22,6 +22,7 @@ import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.Repository; import org.apache.archiva.repository.RepositoryException; import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; +import org.apache.archiva.repository.base.ConfigurationHandler; import java.util.Map; import java.util.TreeMap; @@ -31,6 +32,11 @@ public class RepositoryRegistryMock extends ArchivaRepositoryRegistry private Map managedRepositories = new TreeMap<>(); + public RepositoryRegistryMock( ConfigurationHandler configurationHandler ) + { + super( configurationHandler ); + } + @Override public ManagedRepository putRepository(ManagedRepository managedRepository) throws RepositoryException { diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/configuration/StubConfiguration.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/configuration/StubConfiguration.java index 470f24b07..6a34278f6 100644 --- a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/configuration/StubConfiguration.java +++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/configuration/StubConfiguration.java @@ -56,6 +56,12 @@ public class StubConfiguration this.configuration = configuration; } + @Override + public void save( Configuration configuration, String eventTag ) throws RegistryException, IndeterminateConfigurationException + { + this.configuration = configuration; + } + @Override public boolean isDefaulted() { diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/configuration/TestConfiguration.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/configuration/TestConfiguration.java index 9914da986..78625d715 100644 --- a/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/configuration/TestConfiguration.java +++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/mock/configuration/TestConfiguration.java @@ -51,6 +51,12 @@ public class TestConfiguration this.configuration = configuration; } + @Override + public void save( Configuration configuration, String eventTag ) throws RegistryException, IndeterminateConfigurationException + { + this.configuration = configuration; + } + @Override public boolean isDefaulted() { diff --git a/archiva-modules/archiva-maven/archiva-maven-scheduler/src/test/java/org/apache/archiva/scheduler/indexing/maven/ArchivaIndexingTaskExecutorTest.java b/archiva-modules/archiva-maven/archiva-maven-scheduler/src/test/java/org/apache/archiva/scheduler/indexing/maven/ArchivaIndexingTaskExecutorTest.java index 450ebd3ef..d778d5c3b 100644 --- a/archiva-modules/archiva-maven/archiva-maven-scheduler/src/test/java/org/apache/archiva/scheduler/indexing/maven/ArchivaIndexingTaskExecutorTest.java +++ b/archiva-modules/archiva-maven/archiva-maven-scheduler/src/test/java/org/apache/archiva/scheduler/indexing/maven/ArchivaIndexingTaskExecutorTest.java @@ -26,6 +26,7 @@ import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; import org.apache.archiva.repository.base.BasicManagedRepository; import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.ReleaseScheme; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.repository.features.IndexCreationFeature; import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask; @@ -73,6 +74,9 @@ public class ArchivaIndexingTaskExecutorTest @Inject ArchivaRepositoryRegistry repositoryRegistry; + @Inject + RepositoryGroupHandler repositoryGroupHandler; + @Inject private IndexUpdater indexUpdater; diff --git a/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/test/java/org/apache/archiva/scheduler/repository/AbstractArchivaRepositoryScanningTaskExecutorTest.java b/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/test/java/org/apache/archiva/scheduler/repository/AbstractArchivaRepositoryScanningTaskExecutorTest.java index 1a6d39070..443078efb 100644 --- a/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/test/java/org/apache/archiva/scheduler/repository/AbstractArchivaRepositoryScanningTaskExecutorTest.java +++ b/archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/test/java/org/apache/archiva/scheduler/repository/AbstractArchivaRepositoryScanningTaskExecutorTest.java @@ -29,6 +29,7 @@ import org.apache.archiva.mock.MockRepositorySessionFactory; import org.apache.archiva.components.taskqueue.execution.TaskExecutor; import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.RepositoryRegistry; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.scheduler.repository.model.RepositoryTask; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.junit.After; @@ -65,6 +66,9 @@ public abstract class AbstractArchivaRepositoryScanningTaskExecutorTest @Inject RepositoryRegistry repositoryRegistry; + @Inject + RepositoryGroupHandler groupHandler; + @Inject @Named( value = "taskExecutor#test-repository-scanning" ) protected TaskExecutor taskExecutor; diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java index 8a5b6eaeb..a95c68f95 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java @@ -55,20 +55,20 @@ import static org.apache.archiva.rest.api.services.v2.RestConfiguration.DEFAULT_ * @since 3.0 */ @Path( "/repository_groups" ) -@Schema( name="RepositoryGroups", description = "Managing of repository groups or virtual repositories") +@Schema( name = "RepositoryGroups", description = "Managing of repository groups or virtual repositories" ) public interface RepositoryGroupService { @Path( "" ) @GET - @Produces( { APPLICATION_JSON } ) + @Produces( {APPLICATION_JSON} ) @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) @Operation( summary = "Returns all repository group entries.", parameters = { - @Parameter(name = "q", description = "Search term"), - @Parameter(name = "offset", description = "The offset of the first element returned"), - @Parameter(name = "limit", description = "Maximum number of items to return in the response"), - @Parameter(name = "orderBy", description = "List of attribute used for sorting (key, value)"), - @Parameter(name = "order", description = "The sort order. Either ascending (asc) or descending (desc)") + @Parameter( name = "q", description = "Search term" ), + @Parameter( name = "offset", description = "The offset of the first element returned" ), + @Parameter( name = "limit", description = "Maximum number of items to return in the response" ), + @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ), + @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" ) }, security = { @SecurityRequirement( @@ -78,22 +78,22 @@ public interface RepositoryGroupService responses = { @ApiResponse( responseCode = "200", description = "If the list could be returned", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PagedResult.class)) + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) ) ), @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) } ) - PagedResult getRepositoriesGroups(@QueryParam("q") @DefaultValue( "" ) String searchTerm, - @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, - @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit, - @QueryParam( "orderBy") @DefaultValue( "id" ) List orderBy, - @QueryParam("order") @DefaultValue( "asc" ) String order) + PagedResult getRepositoriesGroups( @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm, + @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, + @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit, + @QueryParam( "orderBy" ) @DefaultValue( "id" ) List orderBy, + @QueryParam( "order" ) @DefaultValue( "asc" ) String order ) throws ArchivaRestServiceException; @Path( "{repositoryGroupId}" ) @GET - @Produces( { APPLICATION_JSON } ) + @Produces( {APPLICATION_JSON} ) @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) @Operation( summary = "Returns a single repository group configuration.", security = { @@ -104,12 +104,12 @@ public interface RepositoryGroupService responses = { @ApiResponse( responseCode = "200", description = "If the configuration is returned", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RepositoryGroup.class)) + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) ), @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), @ApiResponse( responseCode = "404", description = "The repository group with the given id does not exist", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) } ) RepositoryGroup getRepositoryGroup( @PathParam( "repositoryGroupId" ) String repositoryGroupId ) @@ -117,14 +117,14 @@ public interface RepositoryGroupService @Path( "" ) @POST - @Consumes( { APPLICATION_JSON } ) - @Produces( { APPLICATION_JSON } ) + @Consumes( {APPLICATION_JSON} ) + @Produces( {APPLICATION_JSON} ) @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) @Operation( summary = "Creates a new group entry.", requestBody = - @RequestBody(required = true, description = "The configuration of the repository group.", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RepositoryGroup.class)) - ) + @RequestBody( required = true, description = "The configuration of the repository group.", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) + ) , security = { @SecurityRequirement( @@ -134,17 +134,17 @@ public interface RepositoryGroupService responses = { @ApiResponse( responseCode = "201", description = "If the list could be returned", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RepositoryGroup.class)) + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) ), @ApiResponse( responseCode = "303", description = "The repository group exists already", headers = { - @Header( name="Location", description = "The URL of existing group", schema = @Schema(type="string")) + @Header( name = "Location", description = "The URL of existing group", schema = @Schema( type = "string" ) ) } ), @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), @ApiResponse( responseCode = "422", description = "The body data is not valid", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) } ) RepositoryGroup addRepositoryGroup( RepositoryGroup repositoryGroup ) @@ -152,13 +152,13 @@ public interface RepositoryGroupService @Path( "{repositoryGroupId}" ) @PUT - @Consumes( { APPLICATION_JSON } ) - @Produces( { APPLICATION_JSON } ) + @Consumes( {APPLICATION_JSON} ) + @Produces( {APPLICATION_JSON} ) @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) @Operation( summary = "Returns all repository group entries.", requestBody = - @RequestBody(required = true, description = "The configuration of the repository group.", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RepositoryGroup.class)) + @RequestBody( required = true, description = "The configuration of the repository group.", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) ) , security = { @@ -169,14 +169,14 @@ public interface RepositoryGroupService responses = { @ApiResponse( responseCode = "200", description = "If the group is returned", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RepositoryGroup.class)) + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) ), @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), @ApiResponse( responseCode = "404", description = "The group with the given id does not exist", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), @ApiResponse( responseCode = "422", description = "The body data is not valid", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) } ) RepositoryGroup updateRepositoryGroup( @PathParam( "repositoryGroupId" ) String groupId, RepositoryGroup repositoryGroup ) @@ -184,7 +184,7 @@ public interface RepositoryGroupService @Path( "{repositoryGroupId}" ) @DELETE - @Produces( { APPLICATION_JSON } ) + @Produces( {APPLICATION_JSON} ) @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) @Operation( summary = "Deletes the repository group entry with the given id.", security = { @@ -197,9 +197,9 @@ public interface RepositoryGroupService description = "If the group was deleted" ), @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), @ApiResponse( responseCode = "404", description = "The group with the given id does not exist", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), } ) Response deleteRepositoryGroup( @PathParam( "repositoryGroupId" ) String repositoryGroupId ) @@ -207,7 +207,7 @@ public interface RepositoryGroupService @Path( "{repositoryGroupId}/repositories/{repositoryId}" ) @PUT - @Produces( { APPLICATION_JSON } ) + @Produces( {APPLICATION_JSON} ) @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) @Operation( summary = "Adds the repository with the given id to the repository group.", security = { @@ -220,18 +220,18 @@ public interface RepositoryGroupService description = "If the repository was added or if it was already part of the group" ), @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), @ApiResponse( responseCode = "404", description = "The group with the given id does not exist", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), } ) RepositoryGroup addRepositoryToGroup( @PathParam( "repositoryGroupId" ) String repositoryGroupId, - @PathParam( "repositoryId" ) String repositoryId ) + @PathParam( "repositoryId" ) String repositoryId ) throws ArchivaRestServiceException; @Path( "{repositoryGroupId}/repositories/{repositoryId}" ) @DELETE - @Produces( { APPLICATION_JSON } ) + @Produces( {APPLICATION_JSON} ) @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) @Operation( summary = "Removes the repository with the given id from the repository group.", security = { @@ -244,13 +244,13 @@ public interface RepositoryGroupService description = "If the repository was removed." ), @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), @ApiResponse( responseCode = "404", description = "The group with the given id does not exist, or the repository was not part of the group.", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), } ) RepositoryGroup deleteRepositoryFromGroup( @PathParam( "repositoryGroupId" ) String repositoryGroupId, - @PathParam( "repositoryId" ) String repositoryId ) + @PathParam( "repositoryId" ) String repositoryId ) throws ArchivaRestServiceException; diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/MavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/maven/MavenManagedRepositoryService.java similarity index 98% rename from archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/MavenManagedRepositoryService.java rename to archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/maven/MavenManagedRepositoryService.java index 5aff95ef6..5e63682ee 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/MavenManagedRepositoryService.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/maven/MavenManagedRepositoryService.java @@ -1,4 +1,4 @@ -package org.apache.archiva.rest.api.services.v2; +package org.apache.archiva.rest.api.services.v2.maven; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -31,6 +31,8 @@ import org.apache.archiva.redback.authorization.RedbackAuthorization; import org.apache.archiva.rest.api.model.v2.FileInfo; import org.apache.archiva.rest.api.model.v2.MavenManagedRepository; import org.apache.archiva.rest.api.model.v2.MavenManagedRepositoryUpdate; +import org.apache.archiva.rest.api.services.v2.ArchivaRestError; +import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException; import org.apache.archiva.security.common.ArchivaRoleConstants; import javax.ws.rs.Consumes; @@ -51,6 +53,8 @@ import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static org.apache.archiva.rest.api.services.v2.RestConfiguration.DEFAULT_PAGE_LIMIT; /** + * Service interface for managing managed maven repositories + * * @author Martin Stockhammer * @since 3.0 */ diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java index f99b06db7..06c2e4ee6 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRepositoriesService.java @@ -47,6 +47,7 @@ import org.apache.archiva.redback.system.SecuritySystem; import org.apache.archiva.redback.users.User; import org.apache.archiva.redback.users.UserManagerException; import org.apache.archiva.redback.users.UserNotFoundException; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.repository.content.BaseRepositoryContentLayout; import org.apache.archiva.repository.content.ContentNotFoundException; import org.apache.archiva.repository.content.LayoutException; @@ -128,6 +129,10 @@ public class DefaultRepositoriesService @Inject private RepositoryRegistry repositoryRegistry; + @SuppressWarnings( "unused" ) + @Inject + private RepositoryGroupHandler repositoryGroupHandler; + @Inject private SecuritySystem securitySystem; diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/utils/AuditHelper.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/utils/AuditHelper.java new file mode 100644 index 000000000..b6b4acae6 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/utils/AuditHelper.java @@ -0,0 +1,40 @@ +package org.apache.archiva.rest.services.utils; +/* + * 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.admin.model.AuditInformation; +import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal; +import org.apache.archiva.redback.rest.services.RedbackRequestInformation; +import org.apache.archiva.redback.users.User; + +/** + * @author Martin Stockhammer + */ +public class AuditHelper +{ + private static final AuditInformation NULL_RESULT = new AuditInformation( null, null ); + public static AuditInformation getAuditData() { + RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get( ); + if (redbackRequestInformation==null) { + return NULL_RESULT; + } else + { + return new AuditInformation( redbackRequestInformation.getUser( ), redbackRequestInformation.getRemoteAddr( ) ); + } + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java index 6fd85d5cf..7b776a7f7 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java @@ -35,35 +35,28 @@ import org.apache.archiva.redback.users.UserNotFoundException; import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.ReleaseScheme; import org.apache.archiva.repository.Repository; -import org.apache.archiva.repository.RepositoryException; import org.apache.archiva.repository.RepositoryRegistry; import org.apache.archiva.repository.RepositoryType; import org.apache.archiva.repository.content.ContentItem; import org.apache.archiva.repository.content.LayoutException; -import org.apache.archiva.repository.storage.fs.FilesystemStorage; import org.apache.archiva.repository.storage.fs.FsStorageUtil; -import org.apache.archiva.repository.storage.util.StorageUtil; -import org.apache.archiva.rest.api.model.v2.Artifact; import org.apache.archiva.rest.api.model.v2.FileInfo; import org.apache.archiva.rest.api.model.v2.MavenManagedRepository; import org.apache.archiva.rest.api.model.v2.MavenManagedRepositoryUpdate; import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException; import org.apache.archiva.rest.api.services.v2.ErrorKeys; import org.apache.archiva.rest.api.services.v2.ErrorMessage; -import org.apache.archiva.rest.api.services.v2.MavenManagedRepositoryService; +import org.apache.archiva.rest.api.services.v2.maven.MavenManagedRepositoryService; import org.apache.archiva.security.common.ArchivaRoleConstants; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import javax.inject.Inject; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.PathParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Comparator; @@ -103,7 +96,9 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit private RepositoryRegistry repositoryRegistry; private SecuritySystem securitySystem; - public DefaultMavenManagedRepositoryService( SecuritySystem securitySystem, RepositoryRegistry repositoryRegistry, ManagedRepositoryAdmin managedRepositoryAdmin ) + public DefaultMavenManagedRepositoryService( SecuritySystem securitySystem, + RepositoryRegistry repositoryRegistry, + ManagedRepositoryAdmin managedRepositoryAdmin ) { this.securitySystem = securitySystem; this.repositoryRegistry = repositoryRegistry; @@ -113,8 +108,16 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit protected AuditInformation getAuditInformation( ) { RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get( ); - User user = redbackRequestInformation == null ? null : redbackRequestInformation.getUser( ); - String remoteAddr = redbackRequestInformation == null ? null : redbackRequestInformation.getRemoteAddr( ); + User user; + String remoteAddr; + if (redbackRequestInformation==null) { + user = null; + remoteAddr = null; + } else + { + user = redbackRequestInformation.getUser( ); + remoteAddr = redbackRequestInformation.getRemoteAddr( ); + } return new AuditInformation( user, remoteAddr ); } diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java index 9290873d6..44ce638ac 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java @@ -34,16 +34,12 @@ package org.apache.archiva.rest.services.v2;/* * under the License. */ -import org.apache.archiva.admin.model.AuditInformation; import org.apache.archiva.admin.model.EntityExistsException; import org.apache.archiva.admin.model.EntityNotFoundException; import org.apache.archiva.admin.model.RepositoryAdminException; import org.apache.archiva.admin.model.group.RepositoryGroupAdmin; import org.apache.archiva.components.rest.model.PagedResult; import org.apache.archiva.components.rest.util.QueryHelper; -import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal; -import org.apache.archiva.redback.rest.services.RedbackRequestInformation; -import org.apache.archiva.redback.users.User; import org.apache.archiva.rest.api.model.v2.RepositoryGroup; import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException; import org.apache.archiva.rest.api.services.v2.ErrorKeys; @@ -54,7 +50,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import javax.inject.Inject; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; @@ -65,6 +60,8 @@ import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; +import static org.apache.archiva.rest.services.utils.AuditHelper.getAuditData; + /** * REST V2 Implementation for repository groups. * @@ -81,8 +78,7 @@ public class DefaultRepositoryGroupService implements RepositoryGroupService @Context UriInfo uriInfo; - @Inject - private RepositoryGroupAdmin repositoryGroupAdmin; + final private RepositoryGroupAdmin repositoryGroupAdmin; private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryGroupService.class ); private static final QueryHelper QUERY_HELPER = new QueryHelper<>( new String[]{"id"} ); @@ -93,12 +89,8 @@ public class DefaultRepositoryGroupService implements RepositoryGroupService } - protected AuditInformation getAuditInformation( ) - { - RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get( ); - User user = redbackRequestInformation == null ? null : redbackRequestInformation.getUser( ); - String remoteAddr = redbackRequestInformation == null ? null : redbackRequestInformation.getRemoteAddr( ); - return new AuditInformation( user, remoteAddr ); + public DefaultRepositoryGroupService(RepositoryGroupAdmin repositoryGroupAdmin) { + this.repositoryGroupAdmin = repositoryGroupAdmin; } @Override @@ -166,7 +158,7 @@ public class DefaultRepositoryGroupService implements RepositoryGroupService { try { - Boolean result = repositoryGroupAdmin.addRepositoryGroup( toModel( repositoryGroup ), getAuditInformation( ) ); + Boolean result = repositoryGroupAdmin.addRepositoryGroup( toModel( repositoryGroup ), getAuditData() ); if ( result ) { org.apache.archiva.admin.model.beans.RepositoryGroup newGroup = repositoryGroupAdmin.getRepositoryGroup( repositoryGroup.getId( ) ); @@ -243,7 +235,7 @@ public class DefaultRepositoryGroupService implements RepositoryGroupService { updateGroup.setMergedIndexTtl( originGroup.getMergedIndexTtl( ) ); } - repositoryGroupAdmin.updateRepositoryGroup( updateGroup, getAuditInformation( ) ); + repositoryGroupAdmin.updateRepositoryGroup( updateGroup, getAuditData( ) ); return RepositoryGroup.of( repositoryGroupAdmin.getRepositoryGroup( repositoryGroupId ) ); } catch ( EntityNotFoundException e ) @@ -265,7 +257,7 @@ public class DefaultRepositoryGroupService implements RepositoryGroupService } try { - Boolean deleted = repositoryGroupAdmin.deleteRepositoryGroup( repositoryGroupId, getAuditInformation( ) ); + Boolean deleted = repositoryGroupAdmin.deleteRepositoryGroup( repositoryGroupId, getAuditData( ) ); if ( !deleted ) { throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_DELETE_FAILED ) ); @@ -297,7 +289,7 @@ public class DefaultRepositoryGroupService implements RepositoryGroupService } try { - repositoryGroupAdmin.addRepositoryToGroup( repositoryGroupId, repositoryId, getAuditInformation( ) ); + repositoryGroupAdmin.addRepositoryToGroup( repositoryGroupId, repositoryId, getAuditData( ) ); return RepositoryGroup.of( repositoryGroupAdmin.getRepositoryGroup( repositoryGroupId ) ); } catch ( EntityNotFoundException e ) @@ -335,7 +327,7 @@ public class DefaultRepositoryGroupService implements RepositoryGroupService } try { - repositoryGroupAdmin.deleteRepositoryFromGroup( repositoryGroupId, repositoryId, getAuditInformation( ) ); + repositoryGroupAdmin.deleteRepositoryFromGroup( repositoryGroupId, repositoryId, getAuditData( ) ); return RepositoryGroup.of( repositoryGroupAdmin.getRepositoryGroup( repositoryGroupId ) ); } catch ( EntityNotFoundException e ) diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml index 53b445abb..46dbc499a 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml @@ -29,11 +29,8 @@ http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd" default-lazy-init="true"> - - - + + + diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/AbstractNativeRestServices.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/AbstractNativeRestServices.java index 06d6f7429..18093fa21 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/AbstractNativeRestServices.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/AbstractNativeRestServices.java @@ -378,7 +378,7 @@ public abstract class AbstractNativeRestServices } else { - log.error( "Serer is not in STARTED state!" ); + log.error( "Server is not in STARTED state!" ); } } @@ -410,15 +410,11 @@ public abstract class AbstractNativeRestServices this.requestSpec = getRequestSpecBuilder( ).build( ); RestAssured.basePath = basePath; RestAssured.config = RestAssuredConfig.config().objectMapperConfig(new ObjectMapperConfig().jackson2ObjectMapperFactory( - new Jackson2ObjectMapperFactory() { - @Override - public ObjectMapper create( Type cls, String charset) { - ObjectMapper om = new ObjectMapper().findAndRegisterModules(); - om.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - om.setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE ); - return om; - } - + ( cls, charset ) -> { + ObjectMapper om = new ObjectMapper().findAndRegisterModules(); + om.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + om.setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE ); + return om; } )); } diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeMavenManagedRepositoryServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeMavenManagedRepositoryServiceTest.java new file mode 100644 index 000000000..f7d137f56 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeMavenManagedRepositoryServiceTest.java @@ -0,0 +1,97 @@ +package org.apache.archiva.rest.services.v2; + +/* + * 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 io.restassured.path.json.JsonPath; +import io.restassured.response.Response; +import io.restassured.response.ResponseBody; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.components.rest.model.PropertyEntry; +import org.apache.archiva.rest.api.model.v2.BeanInformation; +import org.apache.archiva.rest.api.model.v2.CacheConfiguration; +import org.apache.archiva.rest.api.model.v2.LdapConfiguration; +import org.apache.archiva.rest.api.model.v2.MavenManagedRepository; +import org.apache.archiva.rest.api.services.v2.RestConfiguration; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static io.restassured.RestAssured.given; +import static io.restassured.http.ContentType.JSON; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Martin Stockhammer + */ +@TestInstance( TestInstance.Lifecycle.PER_CLASS ) +@Tag( "rest-native" ) +@TestMethodOrder( MethodOrderer.OrderAnnotation.class ) +@DisplayName( "Native REST tests for V2 ManagedRepositoryService" ) +public class NativeMavenManagedRepositoryServiceTest extends AbstractNativeRestServices +{ + @Override + protected String getServicePath( ) + { + return "/repositories/maven/managed"; + } + + @BeforeAll + void setup( ) throws Exception + { + super.setupNative( ); + } + + @AfterAll + void destroy( ) throws Exception + { + super.shutdownNative( ); + } + + @Test + @Order( 1 ) + void testGetRepositories( ) + { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + JsonPath json = response.getBody( ).jsonPath( ); + assertEquals( 2, json.getInt( "pagination.total_count" ) ); + assertEquals( 0, json.getInt( "pagination.offset" ) ); + assertEquals( Integer.valueOf( RestConfiguration.DEFAULT_PAGE_LIMIT ), json.getInt( "pagination.limit" ) ); + List repositories = json.getList( "data", MavenManagedRepository.class ); + assertEquals( "internal", repositories.get( 0 ).getId( ) ); + assertEquals( "snapshots", repositories.get( 1 ).getId( ) ); + } + + + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/resources/META-INF/spring-context-test.xml b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/resources/META-INF/spring-context-test.xml index bec39deeb..19eba026f 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/resources/META-INF/spring-context-test.xml +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/resources/META-INF/spring-context-test.xml @@ -32,7 +32,7 @@ + base-package="org.apache.archiva.redback.keys,org.apache.archiva.rest.services.utils,org.apache.archiva.repository.maven.content"/> diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/AbstractRepositoryServletTestCase.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/AbstractRepositoryServletTestCase.java index 56b8445da..e81e0692b 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/AbstractRepositoryServletTestCase.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/AbstractRepositoryServletTestCase.java @@ -30,6 +30,7 @@ import org.apache.archiva.indexer.ArchivaIndexingContext; import org.apache.archiva.repository.base.ArchivaRepositoryRegistry; import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.RepositoryType; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.apache.archiva.webdav.httpunit.MkColMethodWebRequest; import org.apache.commons.io.FileUtils; @@ -99,6 +100,9 @@ public abstract class AbstractRepositoryServletTestCase @Inject protected ApplicationContext applicationContext; + @SuppressWarnings( "unused" ) + @Inject + RepositoryGroupHandler repositoryGroupHandler; @Inject ArchivaRepositoryRegistry repositoryRegistry; diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/ArchivaDavResourceFactoryTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/ArchivaDavResourceFactoryTest.java index 450a3b92e..e2b259c5c 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/ArchivaDavResourceFactoryTest.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/ArchivaDavResourceFactoryTest.java @@ -34,6 +34,7 @@ import org.apache.archiva.configuration.FileTypes; import org.apache.archiva.configuration.RepositoryGroupConfiguration; import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator; import org.apache.archiva.repository.ManagedRepositoryContent; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.repository.maven.content.MavenContentHelper; import org.apache.archiva.repository.maven.metadata.storage.ArtifactMappingProvider; import org.apache.archiva.proxy.ProxyRegistry; @@ -158,6 +159,10 @@ public class ArchivaDavResourceFactoryTest @Inject FileTypes fileTypes; + @SuppressWarnings( "unused" ) + @Inject + RepositoryGroupHandler repositoryGroupHandler; + public Path getProjectBase() { if (this.projectBase.get()==null) { String pathVal = System.getProperty("mvn.project.base.dir"); @@ -194,8 +199,9 @@ public class ArchivaDavResourceFactoryTest expect (archivaConfiguration.getDefaultLocale()).andReturn( Locale.getDefault() ).anyTimes(); archivaConfiguration.addListener( EasyMock.anyObject( ) ); expectLastCall().times(0, 4); - archivaConfiguration.save( config ); - + archivaConfiguration.save( eq(config)); + expectLastCall().times( 0, 5 ); + archivaConfiguration.save( eq(config), EasyMock.anyString()); expectLastCall().times( 0, 5 ); archivaConfigurationControl.replay(); diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/RepositoryServletSecurityTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/RepositoryServletSecurityTest.java index 0385c25e7..b8310c740 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/RepositoryServletSecurityTest.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/RepositoryServletSecurityTest.java @@ -35,6 +35,7 @@ import org.apache.archiva.redback.users.User; import org.apache.archiva.redback.users.memory.SimpleUser; import org.apache.archiva.repository.RepositoryRegistry; import org.apache.archiva.metadata.audit.TestAuditListener; +import org.apache.archiva.repository.base.RepositoryGroupHandler; import org.apache.archiva.security.ServletAuthenticator; import org.apache.archiva.security.common.ArchivaRoleConstants; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; @@ -91,6 +92,10 @@ public class RepositoryServletSecurityTest @Inject protected RepositoryRegistry repositoryRegistry; + @SuppressWarnings( "unused" ) + @Inject + RepositoryGroupHandler repositoryGroupHandler; + private DavSessionProvider davSessionProvider; private IMocksControl servletAuthControl; -- 2.39.5