You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RepositoryGroupHandlerTest.java 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. package org.apache.archiva.repository.base.group;
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. import org.apache.archiva.common.filelock.DefaultFileLockManager;
  20. import org.apache.archiva.common.filelock.FileLockManager;
  21. import org.apache.archiva.common.utils.FileUtils;
  22. import org.apache.archiva.configuration.ArchivaConfiguration;
  23. import org.apache.archiva.configuration.Configuration;
  24. import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
  25. import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
  26. import org.apache.archiva.configuration.RepositoryGroupConfiguration;
  27. import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler;
  28. import org.apache.archiva.repository.EditableRepositoryGroup;
  29. import org.apache.archiva.repository.ManagedRepository;
  30. import org.apache.archiva.repository.RemoteRepository;
  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.base.remote.BasicRemoteRepository;
  40. import org.apache.archiva.repository.storage.fs.FilesystemStorage;
  41. import org.apache.archiva.repository.validation.CheckedResult;
  42. import org.apache.archiva.repository.validation.ValidationError;
  43. import org.junit.jupiter.api.Test;
  44. import org.junit.jupiter.api.extension.ExtendWith;
  45. import org.mockito.ArgumentMatchers;
  46. import org.mockito.Mock;
  47. import org.mockito.Mockito;
  48. import org.mockito.junit.jupiter.MockitoExtension;
  49. import org.springframework.test.context.ContextConfiguration;
  50. 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;
  60. import java.util.Map;
  61. import static org.apache.archiva.repository.validation.ErrorKeys.ISEMPTY;
  62. import static org.junit.jupiter.api.Assertions.*;
  63. import static org.mockito.ArgumentMatchers.any;
  64. import static org.mockito.ArgumentMatchers.eq;
  65. import static org.mockito.Mockito.verify;
  66. /**
  67. * @author Martin Stockhammer <martin_s@apache.org>
  68. */
  69. @ExtendWith( {MockitoExtension.class, SpringExtension.class} )
  70. @ContextConfiguration( locations = {"classpath*:/META-INF/spring-context.xml", "classpath:/spring-context-group.xml"} )
  71. class RepositoryGroupHandlerTest
  72. {
  73. static {
  74. initialize();
  75. }
  76. @Inject
  77. @Named( "repositoryRegistry" )
  78. ArchivaRepositoryRegistry repositoryRegistry;
  79. @Inject
  80. ConfigurationHandler configurationHandler;
  81. @Mock
  82. // @Named( "mergedRemoteIndexesScheduler#default" )
  83. MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
  84. @Mock
  85. RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration> managedRepositoryHandler;
  86. @Mock
  87. RepositoryHandler<RemoteRepository, RemoteRepositoryConfiguration> remoteRepositoryHandler;
  88. @Inject
  89. ArchivaConfiguration archivaConfiguration;
  90. Path repoBaseDir;
  91. private static void initialize() {
  92. Path baseDir = Paths.get( FileUtils.getBasedir( ) );
  93. Path config = baseDir.resolve( "src/test/resources/archiva-group.xml" );
  94. if ( Files.exists( config ) )
  95. {
  96. Path destConfig = baseDir.resolve( "target/test-classes/archiva-group.xml" );
  97. try
  98. {
  99. Files.copy( config, destConfig );
  100. }
  101. catch ( IOException e )
  102. {
  103. System.err.println( "Could not copy file: " + e.getMessage( ) );
  104. }
  105. }
  106. }
  107. // Helper method that removes a group from the configuration
  108. private void removeGroupFromConfig(String groupId) {
  109. Configuration configuration = configurationHandler.getBaseConfiguration( );
  110. Iterator<RepositoryGroupConfiguration> groupIter = configuration.getRepositoryGroups().iterator();
  111. while(groupIter.hasNext()) {
  112. RepositoryGroupConfiguration group = groupIter.next( );
  113. if (groupId.equals(group.getId())) {
  114. groupIter.remove();
  115. break;
  116. }
  117. }
  118. try
  119. {
  120. configurationHandler.save( configuration );
  121. }
  122. catch ( Throwable e )
  123. {
  124. System.err.println( "Could not remove repo group from config "+groupId );
  125. }
  126. }
  127. private boolean hasGroupInConfig(String groupId) {
  128. assertNotNull( configurationHandler.getBaseConfiguration( ).getRepositoryGroups( ) );
  129. return configurationHandler.getBaseConfiguration( ).getRepositoryGroups( ).stream( ).anyMatch( g -> g != null && groupId.equals( g.getId( ) ) ) ;
  130. }
  131. private RepositoryGroupHandler createHandler( )
  132. {
  133. Mockito.when( managedRepositoryHandler.getVariant( ) ).thenReturn( ManagedRepository.class );
  134. final ManagedRepository internalRepo;
  135. try
  136. {
  137. internalRepo = getManaged( "internal", "internal");
  138. }
  139. catch ( IOException e )
  140. {
  141. throw new Error( e );
  142. }
  143. Mockito.when( managedRepositoryHandler.get( ArgumentMatchers.eq("internal") ) ).thenReturn( internalRepo );
  144. repositoryRegistry.registerHandler( managedRepositoryHandler );
  145. Mockito.when( remoteRepositoryHandler.getVariant( ) ).thenReturn( RemoteRepository.class );
  146. final RemoteRepository centralRepo;
  147. try
  148. {
  149. centralRepo = getRemote( "central", "central");
  150. }
  151. catch ( IOException e )
  152. {
  153. throw new Error( e );
  154. }
  155. repositoryRegistry.registerHandler( remoteRepositoryHandler );
  156. RepositoryGroupHandler groupHandler = new RepositoryGroupHandler( repositoryRegistry, configurationHandler, mergedRemoteIndexesScheduler);
  157. groupHandler.init( );
  158. return groupHandler;
  159. }
  160. private Path getRepoBaseDir() throws IOException
  161. {
  162. if (repoBaseDir==null) {
  163. this.repoBaseDir = archivaConfiguration.getRepositoryBaseDir( ).resolve( "group" );
  164. Files.createDirectories( this.repoBaseDir );
  165. }
  166. return repoBaseDir;
  167. }
  168. protected ManagedRepository getManaged(String id, String name) throws IOException
  169. {
  170. Path path = getRepoBaseDir().resolve( "../managed" );
  171. FileLockManager lockManager = new DefaultFileLockManager();
  172. FilesystemStorage storage = new FilesystemStorage(path.toAbsolutePath(), lockManager);
  173. return new BasicManagedRepository( id, name, storage );
  174. }
  175. protected RemoteRepository getRemote(String id, String name) throws IOException
  176. {
  177. Path path = getRepoBaseDir().resolve( "../remote" );
  178. FileLockManager lockManager = new DefaultFileLockManager();
  179. FilesystemStorage storage = new FilesystemStorage(path.toAbsolutePath(), lockManager);
  180. return new BasicRemoteRepository( id, name, storage );
  181. }
  182. protected EditableRepositoryGroup createRepository( String id, String name, Path location ) throws IOException
  183. {
  184. FileLockManager lockManager = new DefaultFileLockManager();
  185. FilesystemStorage storage = new FilesystemStorage(location.toAbsolutePath(), lockManager);
  186. BasicRepositoryGroup repo = new BasicRepositoryGroup(id, name, storage);
  187. repo.setLocation( location.toAbsolutePath().toUri());
  188. return repo;
  189. }
  190. protected EditableRepositoryGroup createRepository( String id, String name) throws IOException
  191. {
  192. Path dir = getRepoBaseDir( ).resolve( id );
  193. Files.createDirectories( dir );
  194. return createRepository( id, name, dir );
  195. }
  196. @Test
  197. void initializeFromConfig( )
  198. {
  199. RepositoryGroupHandler groupHandler = createHandler( );
  200. groupHandler.initializeFromConfig( );
  201. assertEquals( 1, groupHandler.getAll( ).size( ) );
  202. assertNotNull( groupHandler.get( "test-group-01" ).getRepositories( ) );
  203. assertEquals( "internal", groupHandler.get( "test-group-01" ).getRepositories( ).get( 0 ).getId( ) );
  204. }
  205. @Test
  206. void activateRepository( ) throws RepositoryException
  207. {
  208. String id = "test-group-02";
  209. RepositoryGroupHandler groupHandler = createHandler( );
  210. RepositoryGroup repo = groupHandler.newInstance( RepositoryType.MAVEN, id );
  211. groupHandler.activateRepository( repo );
  212. verify( mergedRemoteIndexesScheduler ).schedule( eq( repo ), any( ) );
  213. assertEquals( RepositoryState.INITIALIZED, repo.getLastState( ) );
  214. assertFalse(hasGroupInConfig( id ));
  215. }
  216. @Test
  217. void newInstancesFromConfig( )
  218. {
  219. RepositoryGroupHandler groupHandler = createHandler( );
  220. Map<String, RepositoryGroup> instances = groupHandler.newInstancesFromConfig( );
  221. assertTrue( instances.containsKey( "test-group-01" ) );
  222. assertEquals( RepositoryState.REFERENCES_SET, instances.get( "test-group-01" ).getLastState( ) );
  223. }
  224. @Test
  225. void newInstance( ) throws RepositoryException
  226. {
  227. String id = "test-group-03";
  228. RepositoryGroupHandler groupHandler = createHandler( );
  229. RepositoryGroup instance = groupHandler.newInstance( RepositoryType.MAVEN, id );
  230. assertNotNull( instance );
  231. assertEquals( id, instance.getId( ) );
  232. assertFalse( groupHandler.hasRepository( id ) );
  233. assertEquals( RepositoryState.REFERENCES_SET, instance.getLastState( ) );
  234. assertFalse( hasGroupInConfig( id ) );
  235. }
  236. @Test
  237. void put( ) throws IOException, RepositoryException
  238. {
  239. final String id = "test-group-04";
  240. try
  241. {
  242. RepositoryGroupHandler groupHandler = createHandler( );
  243. EditableRepositoryGroup repositoryGroup = createRepository( id, "n-"+id );
  244. groupHandler.put( repositoryGroup );
  245. RepositoryGroup storedGroup = groupHandler.get( id );
  246. assertNotNull( storedGroup );
  247. assertEquals( id, storedGroup.getId( ) );
  248. assertEquals( "n-"+id, storedGroup.getName( ) );
  249. EditableRepositoryGroup repositoryGroup2 = createRepository( id, "n2-"+id );
  250. groupHandler.put( repositoryGroup2 );
  251. storedGroup = groupHandler.get( id );
  252. assertNotNull( storedGroup );
  253. assertEquals( id, storedGroup.getId( ) );
  254. assertEquals( "n2-"+id, storedGroup.getName( ) );
  255. assertTrue( hasGroupInConfig( id ));
  256. } finally {
  257. removeGroupFromConfig( id );
  258. }
  259. }
  260. @Test
  261. void putWithConfiguration( ) throws RepositoryException
  262. {
  263. String id = "test-group-05";
  264. try
  265. {
  266. RepositoryGroupHandler groupHandler = createHandler( );
  267. RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
  268. configuration.setId( id );
  269. configuration.setName( "n-" + id );
  270. ArrayList<String> repos = new ArrayList<>( );
  271. repos.add( "internal" );
  272. configuration.setRepositories( repos );
  273. groupHandler.put( configuration );
  274. RepositoryGroup repo = groupHandler.get( id );
  275. assertNotNull( repo );
  276. assertEquals( id, repo.getId( ) );
  277. assertEquals( "n-" + id, repo.getName( ) );
  278. assertNotNull( repo.getRepositories( ) );
  279. assertEquals( 1, repo.getRepositories( ).size( ) );
  280. assertEquals( "internal", repo.getRepositories( ).get( 0 ).getId( ) );
  281. assertTrue( hasGroupInConfig( id ) );
  282. }
  283. finally
  284. {
  285. removeGroupFromConfig( id );
  286. }
  287. }
  288. @Test
  289. void testPutWithoutRegister( ) throws RepositoryException
  290. {
  291. RepositoryGroupHandler groupHandler = createHandler( );
  292. Configuration aCfg = new Configuration( );
  293. RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
  294. final String id = "test-group-06";
  295. configuration.setId( id );
  296. configuration.setName( "n-"+id );
  297. ArrayList<String> repos = new ArrayList<>( );
  298. repos.add( "internal" );
  299. configuration.setRepositories( repos );
  300. groupHandler.put( configuration, aCfg );
  301. RepositoryGroup repo = groupHandler.get( id );
  302. assertNull( repo );
  303. assertFalse( hasGroupInConfig( id ) );
  304. assertTrue( aCfg.getRepositoryGroups( ).stream( ).anyMatch( g -> g!=null && id.equals( g.getId( ) ) ) );
  305. }
  306. @Test
  307. void putWithCheck_invalid( ) throws RepositoryException
  308. {
  309. final String id = "test-group-07";
  310. final String name = "n-"+id;
  311. try
  312. {
  313. RepositoryGroupHandler groupHandler = createHandler( );
  314. BasicRepositoryGroupValidator checker = new BasicRepositoryGroupValidator( configurationHandler );
  315. RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
  316. configuration.setId( "" );
  317. configuration.setName( name );
  318. ArrayList<String> repos = new ArrayList<>( );
  319. repos.add( "internal" );
  320. configuration.setRepositories( repos );
  321. CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.putWithCheck( configuration, checker );
  322. assertNull( groupHandler.get( id ) );
  323. assertNotNull( result.getResult( ) );
  324. assertNotNull( result.getResult( ).get( "id" ) );
  325. assertEquals( 1, result.getResult( ).get( "id" ).size( ) );
  326. assertEquals( ISEMPTY, result.getResult( ).get( "id" ).get( 0 ).getType( ) );
  327. assertFalse( hasGroupInConfig( id ) );
  328. assertFalse( hasGroupInConfig( "" ) );
  329. } finally
  330. {
  331. removeGroupFromConfig( id );
  332. }
  333. }
  334. @Test
  335. void remove( ) throws RepositoryException
  336. {
  337. RepositoryGroupHandler groupHandler = createHandler( );
  338. RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
  339. final String id = "test-group-08";
  340. configuration.setId( id );
  341. configuration.setName( "n-"+id );
  342. groupHandler.put( configuration );
  343. assertTrue( hasGroupInConfig( id ) );
  344. assertNotNull( groupHandler.get( id ) );
  345. groupHandler.remove( id );
  346. assertNull( groupHandler.get( id ) );
  347. assertFalse( hasGroupInConfig( id ) );
  348. }
  349. @Test
  350. void removeWithoutSave( ) throws RepositoryException
  351. {
  352. RepositoryGroupHandler groupHandler = createHandler( );
  353. Configuration aCfg = new Configuration( );
  354. RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
  355. final String id = "test-group-09";
  356. configuration.setId( id );
  357. configuration.setName( "n-"+id );
  358. ArrayList<String> repos = new ArrayList<>( );
  359. repos.add( "internal" );
  360. configuration.setRepositories( repos );
  361. groupHandler.put( configuration, aCfg );
  362. assertTrue( aCfg.getRepositoryGroups( ).stream( ).anyMatch( g -> g != null && id.equals( g.getId( ) ) ) );
  363. groupHandler.remove( id, aCfg );
  364. assertNull( groupHandler.get( id ) );
  365. assertTrue( aCfg.getRepositoryGroups( ).stream( ).noneMatch( g -> g != null && id.equals( g.getId( ) ) ) );
  366. assertNull( groupHandler.get( id ) );
  367. }
  368. @Test
  369. void validateRepository( ) throws IOException
  370. {
  371. RepositoryGroupHandler groupHandler = createHandler( );
  372. final String id = "test-group-10";
  373. EditableRepositoryGroup repositoryGroup = createRepository( id, "n-"+id );
  374. repositoryGroup.setMergedIndexTTL( 5 );
  375. CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepository( repositoryGroup );
  376. assertNotNull( result );
  377. assertEquals( 0, result.getResult( ).size( ) );
  378. repositoryGroup = createRepository( id, "n-test-group-10###" );
  379. result = groupHandler.validateRepository( repositoryGroup );
  380. assertNotNull( result );
  381. assertEquals( 2, result.getResult( ).size( ) );
  382. assertNotNull( result.getResult().get( "merged_index_ttl" ) );
  383. assertNotNull( result.getResult().get( "name" ) );
  384. }
  385. @Test
  386. void validateRepositoryIfExisting( ) throws IOException, RepositoryException
  387. {
  388. final String id = "test-group-11";
  389. try
  390. {
  391. RepositoryGroupHandler groupHandler = createHandler( );
  392. EditableRepositoryGroup repositoryGroup = createRepository( id, "n-" + id );
  393. repositoryGroup.setMergedIndexTTL( 5 );
  394. groupHandler.put( repositoryGroup );
  395. CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepository( repositoryGroup );
  396. assertNotNull( result );
  397. assertEquals( 1, result.getResult( ).size( ) );
  398. } finally
  399. {
  400. removeGroupFromConfig( id );
  401. }
  402. }
  403. @Test
  404. void validateRepositoryForUpdate( ) throws IOException, RepositoryException
  405. {
  406. final String id = "test-group-12";
  407. try
  408. {
  409. RepositoryGroupHandler groupHandler = createHandler( );
  410. EditableRepositoryGroup repositoryGroup = createRepository( id, "n-" + id );
  411. repositoryGroup.setMergedIndexTTL( 5 );
  412. groupHandler.put( repositoryGroup );
  413. CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepositoryForUpdate( repositoryGroup );
  414. assertNotNull( result );
  415. assertEquals( 0, result.getResult( ).size( ) );
  416. } finally
  417. {
  418. removeGroupFromConfig( id );
  419. }
  420. }
  421. @Test
  422. void has( ) throws IOException, RepositoryException
  423. {
  424. final String id = "test-group-13";
  425. try
  426. {
  427. RepositoryGroupHandler groupHandler = createHandler( );
  428. EditableRepositoryGroup repositoryGroup = createRepository( id, "n-" + id );
  429. repositoryGroup.setMergedIndexTTL( 5 );
  430. assertFalse( groupHandler.hasRepository( id ) );
  431. groupHandler.put( repositoryGroup );
  432. assertTrue( groupHandler.hasRepository( id ) );
  433. } finally
  434. {
  435. removeGroupFromConfig( id );
  436. }
  437. }
  438. }