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.ArchivaConfiguration;
25 import org.apache.archiva.configuration.Configuration;
26 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
27 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
28 import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler;
29 import org.apache.archiva.repository.EditableRepositoryGroup;
30 import org.apache.archiva.repository.ManagedRepository;
31 import org.apache.archiva.repository.RepositoryException;
32 import org.apache.archiva.repository.RepositoryGroup;
33 import org.apache.archiva.repository.RepositoryHandler;
34 import org.apache.archiva.repository.RepositoryState;
35 import org.apache.archiva.repository.RepositoryType;
36 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
37 import org.apache.archiva.repository.base.ConfigurationHandler;
38 import org.apache.archiva.repository.base.managed.BasicManagedRepository;
39 import org.apache.archiva.repository.storage.fs.FilesystemStorage;
40 import org.apache.archiva.repository.validation.CheckedResult;
41 import org.apache.archiva.repository.validation.ValidationError;
42 import org.junit.jupiter.api.Test;
43 import org.junit.jupiter.api.extension.ExtendWith;
44 import org.mockito.ArgumentMatchers;
45 import org.mockito.Mock;
46 import org.mockito.Mockito;
47 import org.mockito.junit.jupiter.MockitoExtension;
48 import org.springframework.test.context.ContextConfiguration;
49 import org.springframework.test.context.junit.jupiter.SpringExtension;
51 import javax.inject.Inject;
52 import javax.inject.Named;
53 import java.io.IOException;
54 import java.nio.file.Files;
55 import java.nio.file.Path;
56 import java.nio.file.Paths;
57 import java.util.ArrayList;
58 import java.util.Iterator;
59 import java.util.List;
62 import static org.apache.archiva.repository.validation.ErrorKeys.ISEMPTY;
63 import static org.junit.jupiter.api.Assertions.*;
64 import static org.mockito.ArgumentMatchers.any;
65 import static org.mockito.ArgumentMatchers.eq;
66 import static org.mockito.Mockito.verify;
69 * @author Martin Stockhammer <martin_s@apache.org>
71 @ExtendWith( {MockitoExtension.class, SpringExtension.class} )
72 @ContextConfiguration( locations = {"classpath*:/META-INF/spring-context.xml", "classpath:/spring-context-group.xml"} )
73 class RepositoryGroupHandlerTest
80 @Named( "repositoryRegistry" )
81 ArchivaRepositoryRegistry repositoryRegistry;
84 ConfigurationHandler configurationHandler;
87 // @Named( "mergedRemoteIndexesScheduler#default" )
88 MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
91 RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration> managedRepositoryHandler;
94 ArchivaConfiguration archivaConfiguration;
99 private static void initialize() {
100 Path baseDir = Paths.get( FileUtils.getBasedir( ) );
101 Path config = baseDir.resolve( "src/test/resources/archiva-group.xml" );
102 if ( Files.exists( config ) )
104 Path destConfig = baseDir.resolve( "target/test-classes/archiva-group.xml" );
107 Files.copy( config, destConfig );
109 catch ( IOException e )
111 System.err.println( "Could not copy file: " + e.getMessage( ) );
116 // Helper method that removes a group from the configuration
117 private void removeGroupFromConfig(String groupId) {
118 Configuration configuration = configurationHandler.getBaseConfiguration( );
119 Iterator<RepositoryGroupConfiguration> groupIter = configuration.getRepositoryGroups().iterator();
120 while(groupIter.hasNext()) {
121 RepositoryGroupConfiguration group = groupIter.next( );
122 if (groupId.equals(group.getId())) {
129 configurationHandler.save( configuration );
131 catch ( Throwable e )
133 System.err.println( "Could not remove repo group from config "+groupId );
137 private boolean hasGroupInConfig(String groupId) {
138 assertNotNull( configurationHandler.getBaseConfiguration( ).getRepositoryGroups( ) );
139 return configurationHandler.getBaseConfiguration( ).getRepositoryGroups( ).stream( ).anyMatch( g -> g != null && groupId.equals( g.getId( ) ) ) ;
143 private RepositoryGroupHandler createHandler( )
145 Mockito.when( managedRepositoryHandler.getVariant( ) ).thenReturn( ManagedRepository.class );
146 final ManagedRepository internalRepo;
149 internalRepo = getManaged( "internal", "internal");
151 catch ( IOException e )
153 throw new Error( e );
155 Mockito.when( managedRepositoryHandler.get( ArgumentMatchers.eq("internal") ) ).thenReturn( internalRepo );
156 repositoryRegistry.registerHandler( managedRepositoryHandler );
157 RepositoryGroupHandler groupHandler = new RepositoryGroupHandler( repositoryRegistry, configurationHandler, mergedRemoteIndexesScheduler);
158 groupHandler.init( );
162 private Path getRepoBaseDir() throws IOException
164 if (repoBaseDir==null) {
165 this.repoBaseDir = archivaConfiguration.getRepositoryBaseDir( ).resolve( "group" );
166 Files.createDirectories( this.repoBaseDir );
171 protected ManagedRepository getManaged(String id, String name) throws IOException
173 Path path = getRepoBaseDir().resolve( "../managed" );
174 FileLockManager lockManager = new DefaultFileLockManager();
175 FilesystemStorage storage = new FilesystemStorage(path.toAbsolutePath(), lockManager);
176 return new BasicManagedRepository( id, name, storage );
180 protected EditableRepositoryGroup createRepository( String id, String name, Path location ) throws IOException
182 FileLockManager lockManager = new DefaultFileLockManager();
183 FilesystemStorage storage = new FilesystemStorage(location.toAbsolutePath(), lockManager);
184 BasicRepositoryGroup repo = new BasicRepositoryGroup(id, name, storage);
185 repo.setLocation( location.toAbsolutePath().toUri());
189 protected EditableRepositoryGroup createRepository( String id, String name) throws IOException
191 Path dir = getRepoBaseDir( ).resolve( id );
192 Files.createDirectories( dir );
193 return createRepository( id, name, dir );
198 void initializeFromConfig( )
200 RepositoryGroupHandler groupHandler = createHandler( );
201 groupHandler.initializeFromConfig( );
202 assertEquals( 1, groupHandler.getAll( ).size( ) );
203 assertNotNull( groupHandler.get( "test-group-01" ).getRepositories( ) );
204 assertEquals( "internal", groupHandler.get( "test-group-01" ).getRepositories( ).get( 0 ).getId( ) );
208 void activateRepository( ) throws RepositoryException
210 String id = "test-group-02";
211 RepositoryGroupHandler groupHandler = createHandler( );
212 RepositoryGroup repo = groupHandler.newInstance( RepositoryType.MAVEN, id );
213 groupHandler.activateRepository( repo );
214 verify( mergedRemoteIndexesScheduler ).schedule( eq( repo ), any( ) );
215 assertEquals( RepositoryState.INITIALIZED, repo.getLastState( ) );
216 assertFalse(hasGroupInConfig( id ));
220 void newInstancesFromConfig( )
222 RepositoryGroupHandler groupHandler = createHandler( );
223 Map<String, RepositoryGroup> instances = groupHandler.newInstancesFromConfig( );
224 assertTrue( instances.containsKey( "test-group-01" ) );
225 assertEquals( RepositoryState.REFERENCES_SET, instances.get( "test-group-01" ).getLastState( ) );
229 void newInstance( ) throws RepositoryException
231 String id = "test-group-03";
232 RepositoryGroupHandler groupHandler = createHandler( );
233 RepositoryGroup instance = groupHandler.newInstance( RepositoryType.MAVEN, id );
234 assertNotNull( instance );
235 assertEquals( id, instance.getId( ) );
236 assertFalse( groupHandler.hasRepository( id ) );
237 assertEquals( RepositoryState.REFERENCES_SET, instance.getLastState( ) );
238 assertFalse( hasGroupInConfig( id ) );
243 void put( ) throws IOException, RepositoryException
245 final String id = "test-group-04";
248 RepositoryGroupHandler groupHandler = createHandler( );
249 EditableRepositoryGroup repositoryGroup = createRepository( id, "n-"+id );
250 groupHandler.put( repositoryGroup );
251 RepositoryGroup storedGroup = groupHandler.get( id );
252 assertNotNull( storedGroup );
253 assertEquals( id, storedGroup.getId( ) );
254 assertEquals( "n-"+id, storedGroup.getName( ) );
256 EditableRepositoryGroup repositoryGroup2 = createRepository( id, "n2-"+id );
257 groupHandler.put( repositoryGroup2 );
258 storedGroup = groupHandler.get( id );
259 assertNotNull( storedGroup );
260 assertEquals( id, storedGroup.getId( ) );
261 assertEquals( "n2-"+id, storedGroup.getName( ) );
263 assertTrue( hasGroupInConfig( id ));
265 removeGroupFromConfig( id );
270 void putWithConfiguration( ) throws RepositoryException
272 String id = "test-group-05";
276 RepositoryGroupHandler groupHandler = createHandler( );
277 RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
278 configuration.setId( id );
279 configuration.setName( "n-" + id );
280 ArrayList<String> repos = new ArrayList<>( );
281 repos.add( "internal" );
282 configuration.setRepositories( repos );
283 groupHandler.put( configuration );
285 RepositoryGroup repo = groupHandler.get( id );
286 assertNotNull( repo );
287 assertEquals( id, repo.getId( ) );
288 assertEquals( "n-" + id, repo.getName( ) );
290 assertNotNull( repo.getRepositories( ) );
291 assertEquals( 1, repo.getRepositories( ).size( ) );
292 assertEquals( "internal", repo.getRepositories( ).get( 0 ).getId( ) );
293 assertTrue( hasGroupInConfig( id ) );
297 removeGroupFromConfig( id );
302 void testPutWithoutRegister( ) throws RepositoryException
304 RepositoryGroupHandler groupHandler = createHandler( );
305 Configuration aCfg = new Configuration( );
306 RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
307 final String id = "test-group-06";
308 configuration.setId( id );
309 configuration.setName( "n-"+id );
310 ArrayList<String> repos = new ArrayList<>( );
311 repos.add( "internal" );
312 configuration.setRepositories( repos );
313 groupHandler.put( configuration, aCfg );
315 RepositoryGroup repo = groupHandler.get( id );
317 assertFalse( hasGroupInConfig( id ) );
318 assertTrue( aCfg.getRepositoryGroups( ).stream( ).anyMatch( g -> g!=null && id.equals( g.getId( ) ) ) );
323 void putWithCheck_invalid( ) throws RepositoryException
325 final String id = "test-group-07";
326 final String name = "n-"+id;
329 RepositoryGroupHandler groupHandler = createHandler( );
330 BasicRepositoryGroupValidator checker = new BasicRepositoryGroupValidator( configurationHandler );
331 RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
332 configuration.setId( "" );
333 configuration.setName( name );
334 ArrayList<String> repos = new ArrayList<>( );
335 repos.add( "internal" );
336 configuration.setRepositories( repos );
337 CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.putWithCheck( configuration, checker );
338 assertNull( groupHandler.get( id ) );
339 assertNotNull( result.getResult( ) );
340 assertNotNull( result.getResult( ).get( "id" ) );
341 assertEquals( 1, result.getResult( ).get( "id" ).size( ) );
342 assertEquals( ISEMPTY, result.getResult( ).get( "id" ).get( 0 ).getType( ) );
343 assertFalse( hasGroupInConfig( id ) );
344 assertFalse( hasGroupInConfig( "" ) );
347 removeGroupFromConfig( id );
352 void remove( ) throws RepositoryException
354 RepositoryGroupHandler groupHandler = createHandler( );
355 RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
356 final String id = "test-group-08";
357 configuration.setId( id );
358 configuration.setName( "n-"+id );
359 groupHandler.put( configuration );
360 assertTrue( hasGroupInConfig( id ) );
361 assertNotNull( groupHandler.get( id ) );
362 groupHandler.remove( id );
363 assertNull( groupHandler.get( id ) );
364 assertFalse( hasGroupInConfig( id ) );
368 void removeWithoutSave( ) throws RepositoryException
370 RepositoryGroupHandler groupHandler = createHandler( );
371 Configuration aCfg = new Configuration( );
372 RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
373 final String id = "test-group-09";
374 configuration.setId( id );
375 configuration.setName( "n-"+id );
376 ArrayList<String> repos = new ArrayList<>( );
377 repos.add( "internal" );
378 configuration.setRepositories( repos );
379 groupHandler.put( configuration, aCfg );
380 assertTrue( aCfg.getRepositoryGroups( ).stream( ).anyMatch( g -> g != null && id.equals( g.getId( ) ) ) );
381 groupHandler.remove( id, aCfg );
382 assertNull( groupHandler.get( id ) );
383 assertTrue( aCfg.getRepositoryGroups( ).stream( ).noneMatch( g -> g != null && id.equals( g.getId( ) ) ) );
384 assertNull( groupHandler.get( id ) );
390 void validateRepository( ) throws IOException
392 RepositoryGroupHandler groupHandler = createHandler( );
393 final String id = "test-group-10";
394 EditableRepositoryGroup repositoryGroup = createRepository( id, "n-"+id );
395 repositoryGroup.setMergedIndexTTL( 5 );
396 CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepository( repositoryGroup );
397 assertNotNull( result );
398 assertEquals( 0, result.getResult( ).size( ) );
400 repositoryGroup = createRepository( id, "n-test-group-10###" );
401 result = groupHandler.validateRepository( repositoryGroup );
402 assertNotNull( result );
403 assertEquals( 2, result.getResult( ).size( ) );
404 assertNotNull( result.getResult().get( "merged_index_ttl" ) );
405 assertNotNull( result.getResult().get( "name" ) );
410 void validateRepositoryIfExisting( ) throws IOException, RepositoryException
412 final String id = "test-group-11";
415 RepositoryGroupHandler groupHandler = createHandler( );
416 EditableRepositoryGroup repositoryGroup = createRepository( id, "n-" + id );
417 repositoryGroup.setMergedIndexTTL( 5 );
418 groupHandler.put( repositoryGroup );
419 CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepository( repositoryGroup );
420 assertNotNull( result );
421 assertEquals( 1, result.getResult( ).size( ) );
424 removeGroupFromConfig( id );
430 void validateRepositoryForUpdate( ) throws IOException, RepositoryException
432 final String id = "test-group-12";
435 RepositoryGroupHandler groupHandler = createHandler( );
436 EditableRepositoryGroup repositoryGroup = createRepository( id, "n-" + id );
437 repositoryGroup.setMergedIndexTTL( 5 );
438 groupHandler.put( repositoryGroup );
439 CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepositoryForUpdate( repositoryGroup );
440 assertNotNull( result );
441 assertEquals( 0, result.getResult( ).size( ) );
444 removeGroupFromConfig( id );
449 void has( ) throws IOException, RepositoryException
451 final String id = "test-group-13";
454 RepositoryGroupHandler groupHandler = createHandler( );
455 EditableRepositoryGroup repositoryGroup = createRepository( id, "n-" + id );
456 repositoryGroup.setMergedIndexTTL( 5 );
457 assertFalse( groupHandler.hasRepository( id ) );
458 groupHandler.put( repositoryGroup );
459 assertTrue( groupHandler.hasRepository( id ) );
462 removeGroupFromConfig( id );