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.

RepositoryGroupHandler.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  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.components.registry.RegistryException;
  20. import org.apache.archiva.configuration.Configuration;
  21. import org.apache.archiva.configuration.IndeterminateConfigurationException;
  22. import org.apache.archiva.configuration.RepositoryGroupConfiguration;
  23. import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler;
  24. import org.apache.archiva.repository.RepositoryState;
  25. import org.apache.archiva.repository.base.AbstractRepositoryHandler;
  26. import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
  27. import org.apache.archiva.repository.base.ConfigurationHandler;
  28. import org.apache.archiva.repository.validation.CheckedResult;
  29. import org.apache.archiva.repository.EditableRepository;
  30. import org.apache.archiva.repository.EditableRepositoryGroup;
  31. import org.apache.archiva.repository.ManagedRepository;
  32. import org.apache.archiva.repository.Repository;
  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.RepositoryProvider;
  37. import org.apache.archiva.repository.RepositoryType;
  38. import org.apache.archiva.repository.event.RepositoryEvent;
  39. import org.apache.archiva.repository.features.IndexCreationFeature;
  40. import org.apache.archiva.repository.storage.StorageAsset;
  41. import org.apache.archiva.repository.validation.RepositoryChecker;
  42. import org.apache.archiva.repository.validation.RepositoryValidator;
  43. import org.apache.archiva.repository.validation.ValidationError;
  44. import org.apache.archiva.repository.validation.ValidationResponse;
  45. import org.apache.commons.lang3.StringUtils;
  46. import org.slf4j.Logger;
  47. import org.slf4j.LoggerFactory;
  48. import org.springframework.stereotype.Service;
  49. import javax.annotation.PostConstruct;
  50. import javax.annotation.PreDestroy;
  51. import javax.inject.Named;
  52. import java.io.IOException;
  53. import java.nio.file.Files;
  54. import java.nio.file.Path;
  55. import java.util.Collection;
  56. import java.util.Collections;
  57. import java.util.HashMap;
  58. import java.util.LinkedHashMap;
  59. import java.util.List;
  60. import java.util.Map;
  61. import java.util.concurrent.locks.ReentrantReadWriteLock;
  62. import java.util.stream.Collectors;
  63. import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH;
  64. /**
  65. * This class manages repository groups for the RepositoryRegistry.
  66. * It is tightly coupled with the {@link ArchivaRepositoryRegistry}.
  67. *
  68. * @author Martin Stockhammer <martin_s@apache.org>
  69. */
  70. @Service( "repositoryGroupHandler#default" )
  71. public class RepositoryGroupHandler
  72. extends AbstractRepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration>
  73. implements RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration>
  74. {
  75. private static final Logger log = LoggerFactory.getLogger( RepositoryGroupHandler.class );
  76. private final ArchivaRepositoryRegistry repositoryRegistry;
  77. private final ConfigurationHandler configurationHandler;
  78. private final MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
  79. private final Map<String, RepositoryGroup> repositoryGroups = new HashMap<>( );
  80. private final RepositoryValidator<RepositoryGroup> validator;
  81. private Path groupsDirectory;
  82. /**
  83. * Creates a new instance. All dependencies are injected on the constructor.
  84. *
  85. * @param repositoryRegistry the registry. To avoid circular dependencies via DI, this class registers itself on the registry.
  86. * @param configurationHandler the configuration handler is used to retrieve and save configuration.
  87. * @param mergedRemoteIndexesScheduler the index scheduler is used for merging the indexes from all group members
  88. * @param repositoryValidatorList the list of validators that are registered
  89. */
  90. public RepositoryGroupHandler( ArchivaRepositoryRegistry repositoryRegistry,
  91. ConfigurationHandler configurationHandler,
  92. @Named( "mergedRemoteIndexesScheduler#default" ) MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler,
  93. List<RepositoryValidator<? extends Repository>> repositoryValidatorList
  94. )
  95. {
  96. this.configurationHandler = configurationHandler;
  97. this.mergedRemoteIndexesScheduler = mergedRemoteIndexesScheduler;
  98. this.repositoryRegistry = repositoryRegistry;
  99. this.validator = getCombinedValidatdor( RepositoryGroup.class, repositoryValidatorList );
  100. }
  101. @Override
  102. @PostConstruct
  103. public void init( )
  104. {
  105. log.debug( "Initializing repository group handler " + repositoryRegistry.toString( ) );
  106. initializeStorage( );
  107. // We are registering this class on the registry. This is necessary to avoid circular dependencies via injection.
  108. this.repositoryRegistry.registerGroupHandler( this );
  109. }
  110. @Override
  111. public void initializeFromConfig( )
  112. {
  113. this.repositoryGroups.clear( );
  114. this.repositoryGroups.putAll( newInstancesFromConfig( ) );
  115. for ( RepositoryGroup group : this.repositoryGroups.values( ) )
  116. {
  117. initialize( group );
  118. }
  119. }
  120. private void initializeStorage( )
  121. {
  122. Path baseDir = this.configurationHandler.getArchivaConfiguration( ).getRepositoryGroupBaseDir( );
  123. if ( !Files.exists( baseDir ) )
  124. {
  125. try
  126. {
  127. Files.createDirectories( baseDir );
  128. }
  129. catch ( IOException e )
  130. {
  131. log.error( "Could not create group base directory: {}", e.getMessage( ), e );
  132. }
  133. }
  134. this.groupsDirectory = baseDir;
  135. }
  136. @Override
  137. public void initialize( RepositoryGroup repositoryGroup )
  138. {
  139. StorageAsset indexDirectory = getMergedIndexDirectory( repositoryGroup );
  140. if ( !indexDirectory.exists( ) )
  141. {
  142. try
  143. {
  144. indexDirectory.create( );
  145. }
  146. catch ( IOException e )
  147. {
  148. log.error( "Could not create index directory {} for group {}: {}", indexDirectory, repositoryGroup.getId( ), e.getMessage( ) );
  149. }
  150. }
  151. Path groupPath = groupsDirectory.resolve( repositoryGroup.getId( ) );
  152. if ( !Files.exists( groupPath ) )
  153. {
  154. try
  155. {
  156. Files.createDirectories( groupPath );
  157. }
  158. catch ( IOException e )
  159. {
  160. log.error( "Could not create repository group directory {}", groupPath );
  161. }
  162. }
  163. mergedRemoteIndexesScheduler.schedule( repositoryGroup,
  164. indexDirectory );
  165. setLastState( repositoryGroup, RepositoryState.INITIALIZED );
  166. }
  167. public StorageAsset getMergedIndexDirectory( RepositoryGroup group )
  168. {
  169. if ( group != null )
  170. {
  171. return group.getFeature( IndexCreationFeature.class ).get( ).getLocalIndexPath( );
  172. }
  173. else
  174. {
  175. return null;
  176. }
  177. }
  178. @Override
  179. public Map<String, RepositoryGroup> newInstancesFromConfig( )
  180. {
  181. try
  182. {
  183. List<RepositoryGroupConfiguration> repositoryGroupConfigurations =
  184. this.configurationHandler.getBaseConfiguration( ).getRepositoryGroups( );
  185. if ( repositoryGroupConfigurations == null )
  186. {
  187. return Collections.emptyMap( );
  188. }
  189. Map<String, RepositoryGroup> repositoryGroupMap = new LinkedHashMap<>( repositoryGroupConfigurations.size( ) );
  190. Map<RepositoryType, RepositoryProvider> providerMap = repositoryRegistry.getRepositoryProviderMap( );
  191. for ( RepositoryGroupConfiguration repoConfig : repositoryGroupConfigurations )
  192. {
  193. RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
  194. if ( providerMap.containsKey( repositoryType ) )
  195. {
  196. try
  197. {
  198. RepositoryGroup repo = createNewRepositoryGroup( providerMap.get( repositoryType ), repoConfig );
  199. repositoryGroupMap.put( repo.getId( ), repo );
  200. }
  201. catch ( Exception e )
  202. {
  203. log.error( "Could not create repository group {}: {}", repoConfig.getId( ), e.getMessage( ), e );
  204. }
  205. }
  206. }
  207. return repositoryGroupMap;
  208. }
  209. catch ( Throwable e )
  210. {
  211. log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
  212. return Collections.emptyMap( );
  213. }
  214. }
  215. @Override
  216. public RepositoryGroup newInstance( final RepositoryType type, String id ) throws RepositoryException
  217. {
  218. RepositoryProvider provider = repositoryRegistry.getProvider( type );
  219. RepositoryGroupConfiguration config = new RepositoryGroupConfiguration( );
  220. config.setId( id );
  221. return createNewRepositoryGroup( provider, config );
  222. }
  223. @Override
  224. public RepositoryGroup newInstance( final RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException
  225. {
  226. RepositoryType type = RepositoryType.valueOf( repositoryConfiguration.getType( ) );
  227. RepositoryProvider provider = repositoryRegistry.getProvider( type );
  228. return createNewRepositoryGroup( provider, repositoryConfiguration );
  229. }
  230. private RepositoryGroup createNewRepositoryGroup( RepositoryProvider provider, RepositoryGroupConfiguration config ) throws RepositoryException
  231. {
  232. RepositoryGroup repositoryGroup = provider.createRepositoryGroup( config );
  233. updateReferences( repositoryGroup, config );
  234. if (repositoryGroup instanceof EditableRepository)
  235. {
  236. ( (EditableRepository) repositoryGroup ).setLastState( RepositoryState.REFERENCES_SET );
  237. }
  238. return repositoryGroup;
  239. }
  240. /**
  241. * Adds a new repository group to the current list, or replaces the repository group definition with
  242. * the same id, if it exists already.
  243. * The change is saved to the configuration immediately.
  244. *
  245. * @param repositoryGroup the new repository group.
  246. * @throws RepositoryException if the new repository group could not be saved to the configuration.
  247. */
  248. @Override
  249. public RepositoryGroup put( final RepositoryGroup repositoryGroup ) throws RepositoryException
  250. {
  251. final String id = repositoryGroup.getId( );
  252. RepositoryGroup originRepoGroup = repositoryGroups.remove( id );
  253. try
  254. {
  255. if ( originRepoGroup != null && originRepoGroup != repositoryGroup )
  256. {
  257. this.mergedRemoteIndexesScheduler.unschedule( originRepoGroup );
  258. originRepoGroup.close( );
  259. }
  260. RepositoryProvider provider = repositoryRegistry.getProvider( repositoryGroup.getType( ) );
  261. RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration( repositoryGroup );
  262. ReentrantReadWriteLock.WriteLock configLock = this.configurationHandler.getLock( ).writeLock( );
  263. configLock.lock( );
  264. try
  265. {
  266. Configuration configuration = this.configurationHandler.getBaseConfiguration( );
  267. updateReferences( repositoryGroup, newCfg );
  268. RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( id );
  269. if ( oldCfg != null )
  270. {
  271. configuration.removeRepositoryGroup( oldCfg );
  272. }
  273. configuration.addRepositoryGroup( newCfg );
  274. configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
  275. setLastState( repositoryGroup, RepositoryState.SAVED );
  276. initialize( repositoryGroup );
  277. }
  278. finally
  279. {
  280. configLock.unlock( );
  281. }
  282. repositoryGroups.put( id, repositoryGroup );
  283. setLastState( repositoryGroup, RepositoryState.REGISTERED );
  284. return repositoryGroup;
  285. }
  286. catch ( Exception e )
  287. {
  288. // Rollback
  289. if ( originRepoGroup != null )
  290. {
  291. repositoryGroups.put( id, originRepoGroup );
  292. }
  293. else
  294. {
  295. repositoryGroups.remove( id );
  296. }
  297. log.error( "Exception during configuration update {}", e.getMessage( ), e );
  298. throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ), e);
  299. }
  300. }
  301. /**
  302. * Adds a new repository group or updates the repository with the same id, if it exists already.
  303. * The configuration is saved immediately.
  304. *
  305. * @param repositoryGroupConfiguration the repository configuration
  306. * @return the updated or created repository
  307. * @throws RepositoryException if an error occurs, or the configuration is not valid.
  308. */
  309. @Override
  310. public RepositoryGroup put( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException
  311. {
  312. final String id = repositoryGroupConfiguration.getId( );
  313. final RepositoryType repositoryType = RepositoryType.valueOf( repositoryGroupConfiguration.getType( ) );
  314. final RepositoryProvider provider = repositoryRegistry.getProvider( repositoryType );
  315. RepositoryGroup currentRepository;
  316. ReentrantReadWriteLock.WriteLock configLock = this.configurationHandler.getLock( ).writeLock( );
  317. configLock.lock( );
  318. try
  319. {
  320. Configuration configuration = this.configurationHandler.getBaseConfiguration( );
  321. currentRepository = repositoryRegistry.getRepositoryGroup( id );
  322. RepositoryGroup oldRepository = currentRepository == null ? null : clone( currentRepository );
  323. try
  324. {
  325. if (currentRepository==null) {
  326. currentRepository = put( repositoryGroupConfiguration, configuration );
  327. } else
  328. {
  329. setRepositoryGroupDefaults( repositoryGroupConfiguration );
  330. provider.updateRepositoryGroupInstance( (EditableRepositoryGroup) currentRepository, repositoryGroupConfiguration );
  331. }
  332. configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
  333. updateReferences( currentRepository, repositoryGroupConfiguration );
  334. setLastState( currentRepository, RepositoryState.REFERENCES_SET );
  335. initialize( currentRepository );
  336. this.repositoryGroups.put( id, currentRepository );
  337. setLastState( currentRepository, RepositoryState.REGISTERED );
  338. }
  339. catch ( IndeterminateConfigurationException | RegistryException | RepositoryException e )
  340. {
  341. // Trying a rollback
  342. if ( oldRepository != null )
  343. {
  344. RepositoryGroupConfiguration oldCfg = provider.getRepositoryGroupConfiguration( oldRepository );
  345. provider.updateRepositoryGroupInstance( (EditableRepositoryGroup) currentRepository, oldCfg);
  346. replaceOrAddRepositoryConfig( oldCfg, configuration );
  347. try
  348. {
  349. configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
  350. }
  351. catch ( IndeterminateConfigurationException | RegistryException indeterminateConfigurationException )
  352. {
  353. log.error( "Fatal error, config save during rollback failed: {}", e.getMessage( ), e );
  354. }
  355. updateReferences( oldRepository, oldCfg );
  356. setLastState( oldRepository, RepositoryState.REFERENCES_SET );
  357. initialize( oldRepository );
  358. repositoryGroups.put( id, oldRepository );
  359. setLastState( oldRepository, RepositoryState.REGISTERED );
  360. } else {
  361. repositoryGroups.remove( id );
  362. }
  363. log.error( "Could not save the configuration for repository group {}: {}", id, e.getMessage( ), e );
  364. if (e instanceof RepositoryException) {
  365. throw (RepositoryException) e;
  366. } else
  367. {
  368. throw new RepositoryException( "Could not save the configuration for repository group " + id + ": " + e.getMessage( ) );
  369. }
  370. }
  371. }
  372. finally
  373. {
  374. configLock.unlock( );
  375. }
  376. return currentRepository;
  377. }
  378. @Override
  379. public RepositoryGroup put( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException
  380. {
  381. final String id = repositoryGroupConfiguration.getId( );
  382. final RepositoryType repoType = RepositoryType.valueOf( repositoryGroupConfiguration.getType( ) );
  383. RepositoryGroup repo;
  384. setRepositoryGroupDefaults( repositoryGroupConfiguration );
  385. if ( repositoryGroups.containsKey( id ) )
  386. {
  387. repo = clone( repositoryGroups.get( id ) );
  388. if ( repo instanceof EditableRepositoryGroup )
  389. {
  390. repositoryRegistry.getProvider( repoType ).updateRepositoryGroupInstance( (EditableRepositoryGroup) repo, repositoryGroupConfiguration );
  391. }
  392. else
  393. {
  394. throw new RepositoryException( "The repository is not editable " + id );
  395. }
  396. }
  397. else
  398. {
  399. repo = repositoryRegistry.getProvider( repoType ).createRepositoryGroup( repositoryGroupConfiguration );
  400. setLastState( repo, RepositoryState.CREATED );
  401. }
  402. replaceOrAddRepositoryConfig( repositoryGroupConfiguration, configuration );
  403. updateReferences( repo, repositoryGroupConfiguration );
  404. setLastState( repo, RepositoryState.REFERENCES_SET );
  405. return repo;
  406. }
  407. @Override
  408. public <D> CheckedResult<RepositoryGroup, D> putWithCheck( RepositoryGroupConfiguration repositoryConfiguration, RepositoryChecker<RepositoryGroup, D> checker ) throws RepositoryException
  409. {
  410. final String id = repositoryConfiguration.getId( );
  411. RepositoryGroup currentGroup = repositoryGroups.get( id );
  412. Configuration configuration = configurationHandler.getBaseConfiguration( );
  413. RepositoryGroup repositoryGroup = put( repositoryConfiguration, configuration );
  414. CheckedResult<RepositoryGroup, D> result;
  415. if ( currentGroup == null )
  416. {
  417. result = checker.apply( repositoryGroup );
  418. }
  419. else
  420. {
  421. result = checker.applyForUpdate( repositoryGroup );
  422. }
  423. if ( result.isValid( ) )
  424. {
  425. put( result.getRepository() );
  426. }
  427. return result;
  428. }
  429. private void setRepositoryGroupDefaults( RepositoryGroupConfiguration repositoryGroupConfiguration )
  430. {
  431. if ( StringUtils.isEmpty( repositoryGroupConfiguration.getMergedIndexPath( ) ) )
  432. {
  433. repositoryGroupConfiguration.setMergedIndexPath( DEFAULT_INDEX_PATH );
  434. }
  435. if ( repositoryGroupConfiguration.getMergedIndexTtl( ) <= 0 )
  436. {
  437. repositoryGroupConfiguration.setMergedIndexTtl( 300 );
  438. }
  439. if ( StringUtils.isEmpty( repositoryGroupConfiguration.getCronExpression( ) ) )
  440. {
  441. repositoryGroupConfiguration.setCronExpression( "0 0 03 ? * MON" );
  442. }
  443. }
  444. private void replaceOrAddRepositoryConfig( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration )
  445. {
  446. RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( repositoryGroupConfiguration.getId( ) );
  447. if ( oldCfg != null )
  448. {
  449. configuration.removeRepositoryGroup( oldCfg );
  450. }
  451. configuration.addRepositoryGroup( repositoryGroupConfiguration );
  452. }
  453. public void removeRepositoryFromGroups( ManagedRepository repo )
  454. {
  455. if ( repo != null )
  456. {
  457. repositoryGroups.values( ).stream( ).filter( repoGroup -> repoGroup instanceof EditableRepository ).
  458. map( repoGroup -> (EditableRepositoryGroup) repoGroup ).forEach( repoGroup -> repoGroup.removeRepository( repo ) );
  459. }
  460. }
  461. /**
  462. * Removes a repository group from the registry and configuration, if it exists.
  463. * The change is saved to the configuration immediately.
  464. *
  465. * @param id the id of the repository group to remove
  466. * @throws RepositoryException if a error occurs during configuration save
  467. */
  468. @Override
  469. public void remove( final String id ) throws RepositoryException
  470. {
  471. RepositoryGroup repo = get( id );
  472. if ( repo != null )
  473. {
  474. try
  475. {
  476. repo = repositoryGroups.remove( id );
  477. if ( repo != null )
  478. {
  479. this.mergedRemoteIndexesScheduler.unschedule( repo );
  480. repo.close( );
  481. Configuration configuration = this.configurationHandler.getBaseConfiguration( );
  482. RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
  483. if ( cfg != null )
  484. {
  485. configuration.removeRepositoryGroup( cfg );
  486. }
  487. this.configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
  488. setLastState( repo, RepositoryState.UNREGISTERED );
  489. }
  490. }
  491. catch ( RegistryException | IndeterminateConfigurationException e )
  492. {
  493. // Rollback
  494. log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
  495. repositoryGroups.put( repo.getId( ), repo );
  496. throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
  497. }
  498. }
  499. }
  500. @Override
  501. public void remove( String id, Configuration configuration ) throws RepositoryException
  502. {
  503. RepositoryGroup repo = repositoryGroups.get( id );
  504. if ( repo != null )
  505. {
  506. repo = repositoryGroups.remove( id );
  507. if ( repo != null )
  508. {
  509. this.mergedRemoteIndexesScheduler.unschedule( repo );
  510. repo.close( );
  511. RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById( id );
  512. if ( cfg != null )
  513. {
  514. configuration.removeRepositoryGroup( cfg );
  515. }
  516. setLastState( repo, RepositoryState.UNREGISTERED );
  517. }
  518. }
  519. }
  520. @Override
  521. public RepositoryGroup get( String groupId )
  522. {
  523. return repositoryGroups.get( groupId );
  524. }
  525. @Override
  526. public RepositoryGroup clone( RepositoryGroup repo ) throws RepositoryException
  527. {
  528. RepositoryProvider provider = repositoryRegistry.getProvider( repo.getType( ) );
  529. RepositoryGroupConfiguration cfg = provider.getRepositoryGroupConfiguration( repo );
  530. RepositoryGroup cloned = provider.createRepositoryGroup( cfg );
  531. cloned.registerEventHandler( RepositoryEvent.ANY, repositoryRegistry );
  532. setLastState( cloned, RepositoryState.CREATED );
  533. return cloned;
  534. }
  535. @Override
  536. public void updateReferences( RepositoryGroup repo, RepositoryGroupConfiguration repositoryConfiguration ) throws RepositoryException
  537. {
  538. if ( repo instanceof EditableRepositoryGroup && repositoryConfiguration!=null)
  539. {
  540. EditableRepositoryGroup eGroup = (EditableRepositoryGroup) repo;
  541. eGroup.setRepositories( repositoryConfiguration.getRepositories( ).stream( )
  542. .map( repositoryRegistry::getManagedRepository ).collect( Collectors.toList( ) ) );
  543. }
  544. }
  545. @Override
  546. public Collection<RepositoryGroup> getAll( )
  547. {
  548. return repositoryGroups.values( );
  549. }
  550. @Override
  551. public RepositoryValidator<RepositoryGroup> getValidator( )
  552. {
  553. return this.validator;
  554. }
  555. @Override
  556. public CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> validateRepository( RepositoryGroup repository )
  557. {
  558. return this.validator.apply( repository );
  559. }
  560. @Override
  561. public CheckedResult<RepositoryGroup,Map<String, List<ValidationError>>> validateRepositoryForUpdate( RepositoryGroup repository )
  562. {
  563. return this.validator.applyForUpdate( repository );
  564. }
  565. @Override
  566. public boolean has( String id )
  567. {
  568. return repositoryGroups.containsKey( id );
  569. }
  570. @PreDestroy
  571. private void destroy( )
  572. {
  573. this.close( );
  574. }
  575. @Override
  576. public void close( )
  577. {
  578. for ( RepositoryGroup group : repositoryGroups.values( ) )
  579. {
  580. try
  581. {
  582. mergedRemoteIndexesScheduler.unschedule( group );
  583. group.close( );
  584. }
  585. catch ( Throwable e )
  586. {
  587. log.error( "Could not close repository group {}: {}", group.getId( ), e.getMessage( ) );
  588. }
  589. }
  590. this.repositoryGroups.clear( );
  591. }
  592. }