1 package org.apache.archiva.repository.base.group;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
21 import org.apache.archiva.common.filelock.DefaultFileLockManager;
22 import org.apache.archiva.common.filelock.FileLockManager;
23 import org.apache.archiva.common.utils.FileUtils;
24 import org.apache.archiva.configuration.provider.ArchivaConfiguration;
25 import org.apache.archiva.configuration.model.Configuration;
26 import org.apache.archiva.configuration.model.ManagedRepositoryConfiguration;
27 import org.apache.archiva.configuration.model.RemoteRepositoryConfiguration;
28 import org.apache.archiva.configuration.model.RepositoryGroupConfiguration;
29 import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler;
30 import org.apache.archiva.repository.EditableRepositoryGroup;
31 import org.apache.archiva.repository.ManagedRepository;
32 import org.apache.archiva.repository.RemoteRepository;
33 import org.apache.archiva.repository.RepositoryException;
34 import org.apache.archiva.repository.RepositoryGroup;
35 import org.apache.archiva.repository.RepositoryHandler;
36 import org.apache.archiva.repository.RepositoryState;
37 import org.apache.archiva.repository.RepositoryType;
38 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
39 import org.apache.archiva.repository.base.ConfigurationHandler;
40 import org.apache.archiva.repository.base.managed.BasicManagedRepository;
41 import org.apache.archiva.repository.base.remote.BasicRemoteRepository;
42 import org.apache.archiva.repository.storage.fs.FilesystemStorage;
43 import org.apache.archiva.repository.validation.CheckedResult;
44 import org.apache.archiva.repository.validation.ValidationError;
45 import org.junit.jupiter.api.Test;
46 import org.junit.jupiter.api.extension.ExtendWith;
47 import org.mockito.ArgumentMatchers;
48 import org.mockito.Mock;
49 import org.mockito.Mockito;
50 import org.mockito.junit.jupiter.MockitoExtension;
51 import org.springframework.test.context.ContextConfiguration;
52 import org.springframework.test.context.junit.jupiter.SpringExtension;
54 import javax.inject.Inject;
55 import javax.inject.Named;
56 import java.io.IOException;
57 import java.nio.file.Files;
58 import java.nio.file.Path;
59 import java.nio.file.Paths;
60 import java.util.ArrayList;
61 import java.util.Iterator;
62 import java.util.List;
65 import static org.apache.archiva.repository.validation.ErrorKeys.ISEMPTY;
66 import static org.junit.jupiter.api.Assertions.*;
67 import static org.mockito.ArgumentMatchers.any;
68 import static org.mockito.ArgumentMatchers.eq;
69 import static org.mockito.Mockito.verify;
72 * @author Martin Stockhammer <martin_s@apache.org>
74 @ExtendWith( {MockitoExtension.class, SpringExtension.class} )
75 @ContextConfiguration( locations = {"classpath*:/META-INF/spring-context.xml", "classpath:/spring-context-group.xml"} )
76 class RepositoryGroupHandlerTest
83 @Named( "repositoryRegistry" )
84 ArchivaRepositoryRegistry repositoryRegistry;
87 ConfigurationHandler configurationHandler;
90 // @Named( "mergedRemoteIndexesScheduler#default" )
91 MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
94 RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration> managedRepositoryHandler;
97 RepositoryHandler<RemoteRepository, RemoteRepositoryConfiguration> remoteRepositoryHandler;
100 ArchivaConfiguration archivaConfiguration;
105 private static void initialize() {
106 Path baseDir = Paths.get( FileUtils.getBasedir( ) );
107 Path config = baseDir.resolve( "src/test/resources/archiva-group.xml" );
108 if ( Files.exists( config ) )
110 Path destConfig = baseDir.resolve( "target/test-classes/archiva-group.xml" );
113 Files.copy( config, destConfig );
115 catch ( IOException e )
117 System.err.println( "Could not copy file: " + e.getMessage( ) );
122 // Helper method that removes a group from the configuration
123 private void removeGroupFromConfig(String groupId) {
124 Configuration configuration = configurationHandler.getBaseConfiguration( );
125 Iterator<RepositoryGroupConfiguration> groupIter = configuration.getRepositoryGroups().iterator();
126 while(groupIter.hasNext()) {
127 RepositoryGroupConfiguration group = groupIter.next( );
128 if (groupId.equals(group.getId())) {
135 configurationHandler.save( configuration );
137 catch ( Throwable e )
139 System.err.println( "Could not remove repo group from config "+groupId );
143 private boolean hasGroupInConfig(String groupId) {
144 assertNotNull( configurationHandler.getBaseConfiguration( ).getRepositoryGroups( ) );
145 return configurationHandler.getBaseConfiguration( ).getRepositoryGroups( ).stream( ).anyMatch( g -> g != null && groupId.equals( g.getId( ) ) ) ;
149 private RepositoryGroupHandler createHandler( )
151 Mockito.when( managedRepositoryHandler.getVariant( ) ).thenReturn( ManagedRepository.class );
152 final ManagedRepository internalRepo;
155 internalRepo = getManaged( "internal", "internal");
157 catch ( IOException e )
159 throw new Error( e );
161 Mockito.when( managedRepositoryHandler.get( ArgumentMatchers.eq("internal") ) ).thenReturn( internalRepo );
162 repositoryRegistry.registerHandler( managedRepositoryHandler );
164 Mockito.when( remoteRepositoryHandler.getVariant( ) ).thenReturn( RemoteRepository.class );
165 final RemoteRepository centralRepo;
168 centralRepo = getRemote( "central", "central");
170 catch ( IOException e )
172 throw new Error( e );
174 repositoryRegistry.registerHandler( remoteRepositoryHandler );
177 RepositoryGroupHandler groupHandler = new RepositoryGroupHandler( repositoryRegistry, configurationHandler, mergedRemoteIndexesScheduler);
178 groupHandler.init( );
182 private Path getRepoBaseDir() throws IOException
184 if (repoBaseDir==null) {
185 this.repoBaseDir = archivaConfiguration.getRepositoryBaseDir( ).resolve( "group" );
186 Files.createDirectories( this.repoBaseDir );
191 protected ManagedRepository getManaged(String id, String name) throws IOException
193 Path path = getRepoBaseDir().resolve( "../managed" );
194 FileLockManager lockManager = new DefaultFileLockManager();
195 FilesystemStorage storage = new FilesystemStorage(path.toAbsolutePath(), lockManager);
196 return new BasicManagedRepository( id, name, storage );
199 protected RemoteRepository getRemote(String id, String name) throws IOException
201 Path path = getRepoBaseDir().resolve( "../remote" );
202 FileLockManager lockManager = new DefaultFileLockManager();
203 FilesystemStorage storage = new FilesystemStorage(path.toAbsolutePath(), lockManager);
204 return new BasicRemoteRepository( id, name, storage );
208 protected EditableRepositoryGroup createRepository( String id, String name, Path location ) throws IOException
210 FileLockManager lockManager = new DefaultFileLockManager();
211 FilesystemStorage storage = new FilesystemStorage(location.toAbsolutePath(), lockManager);
212 BasicRepositoryGroup repo = new BasicRepositoryGroup(id, name, storage);
213 repo.setLocation( location.toAbsolutePath().toUri());
217 protected EditableRepositoryGroup createRepository( String id, String name) throws IOException
219 Path dir = getRepoBaseDir( ).resolve( id );
220 Files.createDirectories( dir );
221 return createRepository( id, name, dir );
226 void initializeFromConfig( )
228 RepositoryGroupHandler groupHandler = createHandler( );
229 groupHandler.initializeFromConfig( );
230 assertEquals( 1, groupHandler.getAll( ).size( ) );
231 assertNotNull( groupHandler.get( "test-group-01" ).getRepositories( ) );
232 assertEquals( "internal", groupHandler.get( "test-group-01" ).getRepositories( ).get( 0 ).getId( ) );
236 void activateRepository( ) throws RepositoryException
238 String id = "test-group-02";
239 RepositoryGroupHandler groupHandler = createHandler( );
240 RepositoryGroup repo = groupHandler.newInstance( RepositoryType.MAVEN, id );
241 groupHandler.activateRepository( repo );
242 verify( mergedRemoteIndexesScheduler ).schedule( eq( repo ), any( ) );
243 assertEquals( RepositoryState.INITIALIZED, repo.getLastState( ) );
244 assertFalse(hasGroupInConfig( id ));
248 void newInstancesFromConfig( )
250 RepositoryGroupHandler groupHandler = createHandler( );
251 Map<String, RepositoryGroup> instances = groupHandler.newInstancesFromConfig( );
252 assertTrue( instances.containsKey( "test-group-01" ) );
253 assertEquals( RepositoryState.REFERENCES_SET, instances.get( "test-group-01" ).getLastState( ) );
257 void newInstance( ) throws RepositoryException
259 String id = "test-group-03";
260 RepositoryGroupHandler groupHandler = createHandler( );
261 RepositoryGroup instance = groupHandler.newInstance( RepositoryType.MAVEN, id );
262 assertNotNull( instance );
263 assertEquals( id, instance.getId( ) );
264 assertFalse( groupHandler.hasRepository( id ) );
265 assertEquals( RepositoryState.REFERENCES_SET, instance.getLastState( ) );
266 assertFalse( hasGroupInConfig( id ) );
271 void put( ) throws IOException, RepositoryException
273 final String id = "test-group-04";
276 RepositoryGroupHandler groupHandler = createHandler( );
277 EditableRepositoryGroup repositoryGroup = createRepository( id, "n-"+id );
278 groupHandler.put( repositoryGroup );
279 RepositoryGroup storedGroup = groupHandler.get( id );
280 assertNotNull( storedGroup );
281 assertEquals( id, storedGroup.getId( ) );
282 assertEquals( "n-"+id, storedGroup.getName( ) );
284 EditableRepositoryGroup repositoryGroup2 = createRepository( id, "n2-"+id );
285 groupHandler.put( repositoryGroup2 );
286 storedGroup = groupHandler.get( id );
287 assertNotNull( storedGroup );
288 assertEquals( id, storedGroup.getId( ) );
289 assertEquals( "n2-"+id, storedGroup.getName( ) );
291 assertTrue( hasGroupInConfig( id ));
293 removeGroupFromConfig( id );
298 void putWithConfiguration( ) throws RepositoryException
300 String id = "test-group-05";
304 RepositoryGroupHandler groupHandler = createHandler( );
305 RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
306 configuration.setId( id );
307 configuration.setName( "n-" + id );
308 ArrayList<String> repos = new ArrayList<>( );
309 repos.add( "internal" );
310 configuration.setRepositories( repos );
311 groupHandler.put( configuration );
313 RepositoryGroup repo = groupHandler.get( id );
314 assertNotNull( repo );
315 assertEquals( id, repo.getId( ) );
316 assertEquals( "n-" + id, repo.getName( ) );
318 assertNotNull( repo.getRepositories( ) );
319 assertEquals( 1, repo.getRepositories( ).size( ) );
320 assertEquals( "internal", repo.getRepositories( ).get( 0 ).getId( ) );
321 assertTrue( hasGroupInConfig( id ) );
325 removeGroupFromConfig( id );
330 void testPutWithoutRegister( ) throws RepositoryException
332 RepositoryGroupHandler groupHandler = createHandler( );
333 Configuration aCfg = new Configuration( );
334 RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
335 final String id = "test-group-06";
336 configuration.setId( id );
337 configuration.setName( "n-"+id );
338 ArrayList<String> repos = new ArrayList<>( );
339 repos.add( "internal" );
340 configuration.setRepositories( repos );
341 groupHandler.put( configuration, aCfg );
343 RepositoryGroup repo = groupHandler.get( id );
345 assertFalse( hasGroupInConfig( id ) );
346 assertTrue( aCfg.getRepositoryGroups( ).stream( ).anyMatch( g -> g!=null && id.equals( g.getId( ) ) ) );
351 void putWithCheck_invalid( ) throws RepositoryException
353 final String id = "test-group-07";
354 final String name = "n-"+id;
357 RepositoryGroupHandler groupHandler = createHandler( );
358 BasicRepositoryGroupValidator checker = new BasicRepositoryGroupValidator( configurationHandler );
359 RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
360 configuration.setId( "" );
361 configuration.setName( name );
362 ArrayList<String> repos = new ArrayList<>( );
363 repos.add( "internal" );
364 configuration.setRepositories( repos );
365 CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.putWithCheck( configuration, checker );
366 assertNull( groupHandler.get( id ) );
367 assertNotNull( result.getResult( ) );
368 assertNotNull( result.getResult( ).get( "id" ) );
369 assertEquals( 1, result.getResult( ).get( "id" ).size( ) );
370 assertEquals( ISEMPTY, result.getResult( ).get( "id" ).get( 0 ).getType( ) );
371 assertFalse( hasGroupInConfig( id ) );
372 assertFalse( hasGroupInConfig( "" ) );
375 removeGroupFromConfig( id );
380 void remove( ) throws RepositoryException
382 RepositoryGroupHandler groupHandler = createHandler( );
383 RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
384 final String id = "test-group-08";
385 configuration.setId( id );
386 configuration.setName( "n-"+id );
387 groupHandler.put( configuration );
388 assertTrue( hasGroupInConfig( id ) );
389 assertNotNull( groupHandler.get( id ) );
390 groupHandler.remove( id );
391 assertNull( groupHandler.get( id ) );
392 assertFalse( hasGroupInConfig( id ) );
396 void removeWithoutSave( ) throws RepositoryException
398 RepositoryGroupHandler groupHandler = createHandler( );
399 Configuration aCfg = new Configuration( );
400 RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
401 final String id = "test-group-09";
402 configuration.setId( id );
403 configuration.setName( "n-"+id );
404 ArrayList<String> repos = new ArrayList<>( );
405 repos.add( "internal" );
406 configuration.setRepositories( repos );
407 groupHandler.put( configuration, aCfg );
408 assertTrue( aCfg.getRepositoryGroups( ).stream( ).anyMatch( g -> g != null && id.equals( g.getId( ) ) ) );
409 groupHandler.remove( id, aCfg );
410 assertNull( groupHandler.get( id ) );
411 assertTrue( aCfg.getRepositoryGroups( ).stream( ).noneMatch( g -> g != null && id.equals( g.getId( ) ) ) );
412 assertNull( groupHandler.get( id ) );
418 void validateRepository( ) throws IOException
420 RepositoryGroupHandler groupHandler = createHandler( );
421 final String id = "test-group-10";
422 EditableRepositoryGroup repositoryGroup = createRepository( id, "n-"+id );
423 repositoryGroup.setMergedIndexTTL( 5 );
424 CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepository( repositoryGroup );
425 assertNotNull( result );
426 assertEquals( 0, result.getResult( ).size( ) );
428 repositoryGroup = createRepository( id, "n-test-group-10###" );
429 result = groupHandler.validateRepository( repositoryGroup );
430 assertNotNull( result );
431 assertEquals( 2, result.getResult( ).size( ) );
432 assertNotNull( result.getResult().get( "merged_index_ttl" ) );
433 assertNotNull( result.getResult().get( "name" ) );
438 void validateRepositoryIfExisting( ) throws IOException, RepositoryException
440 final String id = "test-group-11";
443 RepositoryGroupHandler groupHandler = createHandler( );
444 EditableRepositoryGroup repositoryGroup = createRepository( id, "n-" + id );
445 repositoryGroup.setMergedIndexTTL( 5 );
446 groupHandler.put( repositoryGroup );
447 CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepository( repositoryGroup );
448 assertNotNull( result );
449 assertEquals( 1, result.getResult( ).size( ) );
452 removeGroupFromConfig( id );
458 void validateRepositoryForUpdate( ) throws IOException, RepositoryException
460 final String id = "test-group-12";
463 RepositoryGroupHandler groupHandler = createHandler( );
464 EditableRepositoryGroup repositoryGroup = createRepository( id, "n-" + id );
465 repositoryGroup.setMergedIndexTTL( 5 );
466 groupHandler.put( repositoryGroup );
467 CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepositoryForUpdate( repositoryGroup );
468 assertNotNull( result );
469 assertEquals( 0, result.getResult( ).size( ) );
472 removeGroupFromConfig( id );
477 void has( ) throws IOException, RepositoryException
479 final String id = "test-group-13";
482 RepositoryGroupHandler groupHandler = createHandler( );
483 EditableRepositoryGroup repositoryGroup = createRepository( id, "n-" + id );
484 repositoryGroup.setMergedIndexTTL( 5 );
485 assertFalse( groupHandler.hasRepository( id ) );
486 groupHandler.put( repositoryGroup );
487 assertTrue( groupHandler.hasRepository( id ) );
490 removeGroupFromConfig( id );