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.

ArchivaRepositoryRegistry.java 61KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653
  1. package org.apache.archiva.repository.base;
  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. *
  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
  18. * under the License.
  19. */
  20. import org.apache.archiva.components.registry.RegistryException;
  21. import org.apache.archiva.configuration.ArchivaConfiguration;
  22. import org.apache.archiva.configuration.Configuration;
  23. import org.apache.archiva.configuration.ConfigurationEvent;
  24. import org.apache.archiva.configuration.ConfigurationListener;
  25. import org.apache.archiva.configuration.IndeterminateConfigurationException;
  26. import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
  27. import org.apache.archiva.configuration.ProxyConnectorConfiguration;
  28. import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
  29. import org.apache.archiva.configuration.RepositoryGroupConfiguration;
  30. import org.apache.archiva.event.Event;
  31. import org.apache.archiva.event.EventHandler;
  32. import org.apache.archiva.event.EventManager;
  33. import org.apache.archiva.event.EventType;
  34. import org.apache.archiva.indexer.ArchivaIndexManager;
  35. import org.apache.archiva.indexer.ArchivaIndexingContext;
  36. import org.apache.archiva.indexer.IndexCreationFailedException;
  37. import org.apache.archiva.indexer.IndexManagerFactory;
  38. import org.apache.archiva.indexer.IndexUpdateFailedException;
  39. import org.apache.archiva.repository.base.group.RepositoryGroupHandler;
  40. import org.apache.archiva.repository.validation.CheckedResult;
  41. import org.apache.archiva.repository.EditableManagedRepository;
  42. import org.apache.archiva.repository.EditableRemoteRepository;
  43. import org.apache.archiva.repository.EditableRepository;
  44. import org.apache.archiva.repository.ManagedRepository;
  45. import org.apache.archiva.repository.RemoteRepository;
  46. import org.apache.archiva.repository.Repository;
  47. import org.apache.archiva.repository.RepositoryContentFactory;
  48. import org.apache.archiva.repository.RepositoryException;
  49. import org.apache.archiva.repository.RepositoryGroup;
  50. import org.apache.archiva.repository.RepositoryProvider;
  51. import org.apache.archiva.repository.RepositoryRegistry;
  52. import org.apache.archiva.repository.RepositoryType;
  53. import org.apache.archiva.repository.UnsupportedRepositoryTypeException;
  54. import org.apache.archiva.repository.event.LifecycleEvent;
  55. import org.apache.archiva.repository.event.RepositoryEvent;
  56. import org.apache.archiva.repository.event.RepositoryIndexEvent;
  57. import org.apache.archiva.repository.event.RepositoryRegistryEvent;
  58. import org.apache.archiva.repository.features.IndexCreationFeature;
  59. import org.apache.archiva.repository.features.StagingRepositoryFeature;
  60. import org.apache.archiva.repository.metadata.MetadataReader;
  61. import org.apache.archiva.repository.storage.StorageAsset;
  62. import org.apache.archiva.repository.validation.RepositoryValidator;
  63. import org.apache.archiva.repository.validation.ValidationError;
  64. import org.apache.archiva.repository.validation.ValidationResponse;
  65. import org.apache.commons.collections4.ListUtils;
  66. import org.apache.commons.lang3.StringUtils;
  67. import org.slf4j.Logger;
  68. import org.slf4j.LoggerFactory;
  69. import org.springframework.stereotype.Service;
  70. import javax.annotation.PostConstruct;
  71. import javax.annotation.PreDestroy;
  72. import javax.inject.Inject;
  73. import javax.inject.Named;
  74. import java.util.ArrayList;
  75. import java.util.Collection;
  76. import java.util.Collections;
  77. import java.util.HashMap;
  78. import java.util.HashSet;
  79. import java.util.List;
  80. import java.util.Map;
  81. import java.util.Set;
  82. import java.util.TreeSet;
  83. import java.util.concurrent.atomic.AtomicBoolean;
  84. import java.util.concurrent.locks.ReentrantReadWriteLock;
  85. import java.util.stream.Collectors;
  86. import java.util.stream.Stream;
  87. /**
  88. * Registry for repositories. This is the central entry point for repositories. It provides methods for
  89. * retrieving, adding and removing repositories.
  90. * <p>
  91. * The modification methods addXX and removeXX persist the changes immediately to the configuration. If the
  92. * configuration save fails the changes are rolled back.
  93. * <p>
  94. * TODO: Audit events
  95. *
  96. * @since 3.0
  97. */
  98. @Service( "repositoryRegistry" )
  99. public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHandler<Event>,
  100. RepositoryRegistry
  101. {
  102. private static final Logger log = LoggerFactory.getLogger( RepositoryRegistry.class );
  103. /**
  104. * We inject all repository providers
  105. */
  106. @Inject
  107. List<RepositoryProvider> repositoryProviders;
  108. @Inject
  109. IndexManagerFactory indexManagerFactory;
  110. @Inject
  111. List<MetadataReader> metadataReaderList;
  112. @Inject
  113. @Named( "repositoryContentFactory#default" )
  114. RepositoryContentFactory repositoryContentFactory;
  115. private final EventManager eventManager;
  116. private Map<String, ManagedRepository> managedRepositories = new HashMap<>( );
  117. private Map<String, ManagedRepository> uManagedRepository = Collections.unmodifiableMap( managedRepositories );
  118. private Map<String, RemoteRepository> remoteRepositories = new HashMap<>( );
  119. private Map<String, RemoteRepository> uRemoteRepositories = Collections.unmodifiableMap( remoteRepositories );
  120. private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock( );
  121. private RepositoryGroupHandler groupHandler;
  122. private final Set<RepositoryValidator<? extends Repository>> validators;
  123. private final ConfigurationHandler configurationHandler;
  124. private AtomicBoolean groups_initalized = new AtomicBoolean( false );
  125. private AtomicBoolean managed_initialized = new AtomicBoolean( false );
  126. private AtomicBoolean remote_initialized = new AtomicBoolean( false );
  127. public ArchivaRepositoryRegistry( ConfigurationHandler configurationHandler, List<RepositoryValidator<? extends Repository>> validatorList )
  128. {
  129. this.eventManager = new EventManager( this );
  130. this.configurationHandler = configurationHandler;
  131. this.validators = initValidatorList( validatorList );
  132. }
  133. private Set<RepositoryValidator<? extends Repository>> initValidatorList( List<RepositoryValidator<? extends Repository>> validators )
  134. {
  135. TreeSet<RepositoryValidator<? extends Repository>> val = new TreeSet<>( );
  136. for (RepositoryValidator<? extends Repository> validator : validators) {
  137. val.add( validator );
  138. }
  139. return val;
  140. }
  141. @Override
  142. public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration )
  143. {
  144. this.configurationHandler.setArchivaConfiguration( archivaConfiguration );
  145. }
  146. @PostConstruct
  147. private void initialize( )
  148. {
  149. rwLock.writeLock( ).lock( );
  150. try
  151. {
  152. log.debug( "Initializing repository registry" );
  153. updateManagedRepositoriesFromConfig( );
  154. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.MANAGED_REPOS_INITIALIZED, this ) );
  155. managed_initialized.set( true );
  156. updateRemoteRepositoriesFromConfig( );
  157. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.REMOTE_REPOS_INITIALIZED, this ) );
  158. remote_initialized.set( true );
  159. initializeRepositoryGroups( );
  160. for ( RepositoryProvider provider : repositoryProviders )
  161. {
  162. provider.addRepositoryEventHandler( this );
  163. }
  164. this.configurationHandler.addListener( this );
  165. }
  166. finally
  167. {
  168. rwLock.writeLock( ).unlock( );
  169. }
  170. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.RELOADED, this ) );
  171. if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
  172. {
  173. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
  174. }
  175. }
  176. private void initializeRepositoryGroups( )
  177. {
  178. if ( this.groupHandler != null )
  179. {
  180. this.groupHandler.initializeFromConfig( );
  181. this.groups_initalized.set( true );
  182. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.GROUPS_INITIALIZED, this ) );
  183. }
  184. }
  185. public void registerGroupHandler( RepositoryGroupHandler groupHandler )
  186. {
  187. this.groupHandler = groupHandler;
  188. initializeRepositoryGroups( );
  189. if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
  190. {
  191. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
  192. }
  193. }
  194. @PreDestroy
  195. public void destroy( )
  196. {
  197. for ( ManagedRepository rep : managedRepositories.values( ) )
  198. {
  199. rep.close( );
  200. }
  201. managedRepositories.clear( );
  202. for ( RemoteRepository repo : remoteRepositories.values( ) )
  203. {
  204. repo.close( );
  205. }
  206. remoteRepositories.clear( );
  207. groupHandler.close( );
  208. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.DESTROYED, this ) );
  209. }
  210. public Map<RepositoryType, RepositoryProvider> getRepositoryProviderMap( )
  211. {
  212. Map<RepositoryType, RepositoryProvider> map = new HashMap<>( );
  213. if ( repositoryProviders != null )
  214. {
  215. for ( RepositoryProvider provider : repositoryProviders )
  216. {
  217. for ( RepositoryType type : provider.provides( ) )
  218. {
  219. map.put( type, provider );
  220. }
  221. }
  222. }
  223. return map;
  224. }
  225. public RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
  226. {
  227. return repositoryProviders.stream( ).filter( repositoryProvider -> repositoryProvider.provides( ).contains( type ) ).findFirst( ).orElseThrow( ( ) -> new RepositoryException( "Repository type cannot be handled: " + type ) );
  228. }
  229. /*
  230. * Updates the repositories
  231. */
  232. private void updateManagedRepositoriesFromConfig( )
  233. {
  234. try
  235. {
  236. Set<String> configRepoIds = new HashSet<>( );
  237. List<ManagedRepositoryConfiguration> managedRepoConfigs =
  238. configurationHandler.getBaseConfiguration( ).getManagedRepositories( );
  239. if ( managedRepoConfigs == null )
  240. {
  241. return;
  242. }
  243. for ( ManagedRepositoryConfiguration repoConfig : managedRepoConfigs )
  244. {
  245. ManagedRepository repo = putRepository( repoConfig, null );
  246. configRepoIds.add( repoConfig.getId( ) );
  247. if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
  248. {
  249. StagingRepositoryFeature stagF = repo.getFeature( StagingRepositoryFeature.class ).get( );
  250. if ( stagF.getStagingRepository( ) != null )
  251. {
  252. configRepoIds.add( stagF.getStagingRepository( ).getId( ) );
  253. }
  254. }
  255. }
  256. List<String> toRemove = managedRepositories.keySet( ).stream( ).filter( id -> !configRepoIds.contains( id ) ).collect( Collectors.toList( ) );
  257. for ( String id : toRemove )
  258. {
  259. ManagedRepository removed = managedRepositories.remove( id );
  260. removed.close( );
  261. }
  262. }
  263. catch ( Throwable e )
  264. {
  265. log.error( "Could not initialize repositories from config: {}", e.getMessage( ), e );
  266. return;
  267. }
  268. }
  269. private ManagedRepository createNewManagedRepository( RepositoryProvider provider, ManagedRepositoryConfiguration cfg ) throws RepositoryException
  270. {
  271. log.debug( "Creating repo {}", cfg.getId( ) );
  272. ManagedRepository repo = provider.createManagedInstance( cfg );
  273. repo.registerEventHandler( RepositoryEvent.ANY, this );
  274. updateRepositoryReferences( provider, repo, cfg, null );
  275. return repo;
  276. }
  277. private String getStagingId( String repoId )
  278. {
  279. return repoId + StagingRepositoryFeature.STAGING_REPO_POSTFIX;
  280. }
  281. @SuppressWarnings( "unchecked" )
  282. private void updateRepositoryReferences( RepositoryProvider provider, ManagedRepository repo, ManagedRepositoryConfiguration cfg, Configuration configuration ) throws RepositoryException
  283. {
  284. log.debug( "Updating references of repo {}", repo.getId( ) );
  285. if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
  286. {
  287. StagingRepositoryFeature feature = repo.getFeature( StagingRepositoryFeature.class ).get( );
  288. if ( feature.isStageRepoNeeded( ) && feature.getStagingRepository( ) == null )
  289. {
  290. ManagedRepository stageRepo = getManagedRepository( getStagingId( repo.getId( ) ) );
  291. if ( stageRepo == null )
  292. {
  293. stageRepo = getStagingRepository( provider, cfg, configuration );
  294. managedRepositories.put( stageRepo.getId( ), stageRepo );
  295. if ( configuration != null )
  296. {
  297. replaceOrAddRepositoryConfig( provider.getManagedConfiguration( stageRepo ), configuration );
  298. }
  299. pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, stageRepo ) );
  300. }
  301. feature.setStagingRepository( stageRepo );
  302. }
  303. }
  304. if ( repo instanceof EditableManagedRepository )
  305. {
  306. EditableManagedRepository editableRepo = (EditableManagedRepository) repo;
  307. if ( repo.getContent( ) == null )
  308. {
  309. editableRepo.setContent( repositoryContentFactory.getManagedRepositoryContent( repo ) );
  310. editableRepo.getContent( ).setRepository( editableRepo );
  311. }
  312. log.debug( "Index repo: " + repo.hasIndex( ) );
  313. if ( repo.hasIndex( ) && ( repo.getIndexingContext( ) == null || !repo.getIndexingContext( ).isOpen( ) ) )
  314. {
  315. log.debug( "Creating indexing context for {}", repo.getId( ) );
  316. createIndexingContext( editableRepo );
  317. }
  318. }
  319. repo.registerEventHandler( RepositoryEvent.ANY, this );
  320. }
  321. @Override
  322. public ArchivaIndexManager getIndexManager( RepositoryType type )
  323. {
  324. return indexManagerFactory.getIndexManager( type );
  325. }
  326. @Override
  327. public MetadataReader getMetadataReader( final RepositoryType type ) throws UnsupportedRepositoryTypeException
  328. {
  329. if ( metadataReaderList != null )
  330. {
  331. return metadataReaderList.stream( ).filter( mr -> mr.isValidForType( type ) ).findFirst( ).orElseThrow( ( ) -> new UnsupportedRepositoryTypeException( type ) );
  332. }
  333. else
  334. {
  335. throw new UnsupportedRepositoryTypeException( type );
  336. }
  337. }
  338. private void createIndexingContext( EditableRepository editableRepo ) throws RepositoryException
  339. {
  340. if ( editableRepo.supportsFeature( IndexCreationFeature.class ) )
  341. {
  342. ArchivaIndexManager idxManager = getIndexManager( editableRepo.getType( ) );
  343. try
  344. {
  345. editableRepo.setIndexingContext( idxManager.createContext( editableRepo ) );
  346. idxManager.updateLocalIndexPath( editableRepo );
  347. }
  348. catch ( IndexCreationFailedException e )
  349. {
  350. throw new RepositoryException( "Could not create index for repository " + editableRepo.getId( ) + ": " + e.getMessage( ), e );
  351. }
  352. }
  353. }
  354. private ManagedRepository getStagingRepository( RepositoryProvider provider, ManagedRepositoryConfiguration baseRepoCfg, Configuration configuration ) throws RepositoryException
  355. {
  356. ManagedRepository stageRepo = getManagedRepository( getStagingId( baseRepoCfg.getId( ) ) );
  357. if ( stageRepo == null )
  358. {
  359. stageRepo = provider.createStagingInstance( baseRepoCfg );
  360. if ( stageRepo.supportsFeature( StagingRepositoryFeature.class ) )
  361. {
  362. stageRepo.getFeature( StagingRepositoryFeature.class ).get( ).setStageRepoNeeded( false );
  363. }
  364. ManagedRepositoryConfiguration stageCfg = provider.getManagedConfiguration( stageRepo );
  365. updateRepositoryReferences( provider, stageRepo, stageCfg, configuration );
  366. }
  367. return stageRepo;
  368. }
  369. private void updateRemoteRepositoriesFromConfig( )
  370. {
  371. try
  372. {
  373. List<RemoteRepositoryConfiguration> remoteRepoConfigs =
  374. configurationHandler.getBaseConfiguration( ).getRemoteRepositories( );
  375. if ( remoteRepoConfigs == null )
  376. {
  377. return;
  378. }
  379. Set<String> repoIds = new HashSet<>( );
  380. for ( RemoteRepositoryConfiguration repoConfig : remoteRepoConfigs )
  381. {
  382. putRepository( repoConfig, null );
  383. repoIds.add( repoConfig.getId( ) );
  384. }
  385. List<String> toRemove = remoteRepositories.keySet( ).stream( ).filter( id -> !repoIds.contains( id ) ).collect( Collectors.toList( ) );
  386. for ( String id : toRemove )
  387. {
  388. RemoteRepository removed = remoteRepositories.remove( id );
  389. removed.close( );
  390. }
  391. }
  392. catch ( Throwable e )
  393. {
  394. log.error( "Could not initialize remote repositories from config: {}", e.getMessage( ), e );
  395. return;
  396. }
  397. }
  398. private RemoteRepository createNewRemoteRepository( RepositoryProvider provider, RemoteRepositoryConfiguration cfg ) throws RepositoryException
  399. {
  400. log.debug( "Creating remote repo {}", cfg.getId( ) );
  401. RemoteRepository repo = provider.createRemoteInstance( cfg );
  402. updateRepositoryReferences( provider, repo, cfg, null );
  403. return repo;
  404. }
  405. private void updateRepositoryReferences( RepositoryProvider provider, RemoteRepository repo, RemoteRepositoryConfiguration cfg, Configuration configuration ) throws RepositoryException
  406. {
  407. if ( repo instanceof EditableRemoteRepository && repo.getContent( ) == null )
  408. {
  409. EditableRemoteRepository editableRepo = (EditableRemoteRepository) repo;
  410. editableRepo.setContent( repositoryContentFactory.getRemoteRepositoryContent( repo ) );
  411. if ( repo.supportsFeature( IndexCreationFeature.class ) && repo.getIndexingContext( ) == null )
  412. {
  413. createIndexingContext( editableRepo );
  414. }
  415. }
  416. repo.registerEventHandler( RepositoryEvent.ANY, this );
  417. }
  418. /**
  419. * Returns all repositories that are registered. There is no defined order of the returned repositories.
  420. *
  421. * @return a list of managed and remote repositories
  422. */
  423. @Override
  424. public Collection<Repository> getRepositories( )
  425. {
  426. rwLock.readLock( ).lock( );
  427. try
  428. {
  429. return Stream.concat( managedRepositories.values( ).stream( ), remoteRepositories.values( ).stream( ) ).collect( Collectors.toList( ) );
  430. }
  431. finally
  432. {
  433. rwLock.readLock( ).unlock( );
  434. }
  435. }
  436. /**
  437. * Returns only the managed repositories. There is no defined order of the returned repositories.
  438. *
  439. * @return a list of managed repositories
  440. */
  441. @Override
  442. public Collection<ManagedRepository> getManagedRepositories( )
  443. {
  444. rwLock.readLock( ).lock( );
  445. try
  446. {
  447. return uManagedRepository.values( );
  448. }
  449. finally
  450. {
  451. rwLock.readLock( ).unlock( );
  452. }
  453. }
  454. /**
  455. * Returns only the remote repositories. There is no defined order of the returned repositories.
  456. *
  457. * @return a list of remote repositories
  458. */
  459. @Override
  460. public Collection<RemoteRepository> getRemoteRepositories( )
  461. {
  462. rwLock.readLock( ).lock( );
  463. try
  464. {
  465. return uRemoteRepositories.values( );
  466. }
  467. finally
  468. {
  469. rwLock.readLock( ).unlock( );
  470. }
  471. }
  472. @Override
  473. public Collection<RepositoryGroup> getRepositoryGroups( )
  474. {
  475. rwLock.readLock( ).lock( );
  476. try
  477. {
  478. return groupHandler.getAll( );
  479. }
  480. finally
  481. {
  482. rwLock.readLock( ).unlock( );
  483. }
  484. }
  485. /**
  486. * Returns the repository with the given id. The returned repository may be a managed or remote repository.
  487. * It returns null, if no repository is registered with the given id.
  488. *
  489. * @param repoId the repository id
  490. * @return the repository if found, otherwise null
  491. */
  492. @Override
  493. public Repository getRepository( String repoId )
  494. {
  495. rwLock.readLock( ).lock( );
  496. try
  497. {
  498. log.debug( "getRepository {}", repoId );
  499. if ( managedRepositories.containsKey( repoId ) )
  500. {
  501. log.debug( "Managed repo" );
  502. return managedRepositories.get( repoId );
  503. }
  504. else if ( remoteRepositories.containsKey( repoId ) )
  505. {
  506. log.debug( "Remote repo" );
  507. return remoteRepositories.get( repoId );
  508. }
  509. else if ( groupHandler.has( repoId ) )
  510. {
  511. return groupHandler.get( repoId );
  512. }
  513. else
  514. {
  515. return null;
  516. }
  517. }
  518. finally
  519. {
  520. rwLock.readLock( ).unlock( );
  521. }
  522. }
  523. /**
  524. * Convenience method, that returns the managed repository with the given id.
  525. * It returns null, if no managed repository is registered with this id.
  526. *
  527. * @param repoId the repository id
  528. * @return the managed repository if found, otherwise null
  529. */
  530. @Override
  531. public ManagedRepository getManagedRepository( String repoId )
  532. {
  533. rwLock.readLock( ).lock( );
  534. try
  535. {
  536. return managedRepositories.get( repoId );
  537. }
  538. finally
  539. {
  540. rwLock.readLock( ).unlock( );
  541. }
  542. }
  543. /**
  544. * Convenience method, that returns the remote repository with the given id.
  545. * It returns null, if no remote repository is registered with this id.
  546. *
  547. * @param repoId the repository id
  548. * @return the remote repository if found, otherwise null
  549. */
  550. @Override
  551. public RemoteRepository getRemoteRepository( String repoId )
  552. {
  553. rwLock.readLock( ).lock( );
  554. try
  555. {
  556. return remoteRepositories.get( repoId );
  557. }
  558. finally
  559. {
  560. rwLock.readLock( ).unlock( );
  561. }
  562. }
  563. @Override
  564. public RepositoryGroup getRepositoryGroup( String groupId )
  565. {
  566. rwLock.readLock( ).lock( );
  567. try
  568. {
  569. return groupHandler.get( groupId );
  570. }
  571. finally
  572. {
  573. rwLock.readLock( ).unlock( );
  574. }
  575. }
  576. @Override
  577. public boolean hasRepository( String repoId )
  578. {
  579. return this.managedRepositories.containsKey( repoId ) || this.remoteRepositories.containsKey( repoId ) || groupHandler.has( repoId );
  580. }
  581. @Override
  582. public boolean hasManagedRepository( String repoId )
  583. {
  584. return this.managedRepositories.containsKey( repoId );
  585. }
  586. @Override
  587. public boolean hasRemoteRepository( String repoId )
  588. {
  589. return this.remoteRepositories.containsKey( repoId );
  590. }
  591. @Override
  592. public boolean hasRepositoryGroup( String groupId )
  593. {
  594. return groupHandler.has( groupId );
  595. }
  596. protected void saveConfiguration( Configuration configuration ) throws IndeterminateConfigurationException, RegistryException
  597. {
  598. configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
  599. }
  600. /**
  601. * Adds a new repository to the current list, or replaces the repository definition with
  602. * the same id, if it exists already.
  603. * The change is saved to the configuration immediately.
  604. *
  605. * @param managedRepository the new repository.
  606. * @throws RepositoryException if the new repository could not be saved to the configuration.
  607. */
  608. @Override
  609. public ManagedRepository putRepository( ManagedRepository managedRepository ) throws RepositoryException
  610. {
  611. rwLock.writeLock( ).lock( );
  612. try
  613. {
  614. final String id = managedRepository.getId( );
  615. if ( remoteRepositories.containsKey( id ) )
  616. {
  617. throw new RepositoryException( "There exists a remote repository with id " + id + ". Could not update with managed repository." );
  618. }
  619. ManagedRepository originRepo = managedRepositories.put( id, managedRepository );
  620. try
  621. {
  622. if ( originRepo != null && originRepo != managedRepository )
  623. {
  624. originRepo.close( );
  625. }
  626. RepositoryProvider provider = getProvider( managedRepository.getType( ) );
  627. ManagedRepositoryConfiguration newCfg = provider.getManagedConfiguration( managedRepository );
  628. Configuration configuration = configurationHandler.getBaseConfiguration( );
  629. updateRepositoryReferences( provider, managedRepository, newCfg, configuration );
  630. ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( id );
  631. if ( oldCfg != null )
  632. {
  633. configuration.removeManagedRepository( oldCfg );
  634. }
  635. configuration.addManagedRepository( newCfg );
  636. saveConfiguration( configuration );
  637. if ( originRepo != managedRepository )
  638. {
  639. pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, managedRepository ) );
  640. }
  641. else
  642. {
  643. pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, managedRepository ) );
  644. }
  645. return managedRepository;
  646. }
  647. catch ( Exception e )
  648. {
  649. // Rollback only partly, because repository is closed already
  650. if ( originRepo != null )
  651. {
  652. managedRepositories.put( id, originRepo );
  653. }
  654. else
  655. {
  656. managedRepositories.remove( id );
  657. }
  658. log.error( "Exception during configuration update {}", e.getMessage( ), e );
  659. throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ) );
  660. }
  661. }
  662. finally
  663. {
  664. rwLock.writeLock( ).unlock( );
  665. }
  666. }
  667. /**
  668. * Adds a new repository or updates the repository with the same id, if it exists already.
  669. * The configuration is saved immediately.
  670. *
  671. * @param managedRepositoryConfiguration the repository configuration
  672. * @return the updated or created repository
  673. * @throws RepositoryException if an error occurs, or the configuration is not valid.
  674. */
  675. @Override
  676. public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration ) throws RepositoryException
  677. {
  678. rwLock.writeLock( ).lock( );
  679. try
  680. {
  681. final String id = managedRepositoryConfiguration.getId( );
  682. final RepositoryType repositoryType = RepositoryType.valueOf( managedRepositoryConfiguration.getType( ) );
  683. Configuration configuration = configurationHandler.getBaseConfiguration( );
  684. ManagedRepository repo = managedRepositories.get( id );
  685. ManagedRepositoryConfiguration oldCfg = repo != null ? getProvider( repositoryType ).getManagedConfiguration( repo ) : null;
  686. repo = putRepository( managedRepositoryConfiguration, configuration );
  687. try
  688. {
  689. saveConfiguration( configuration );
  690. }
  691. catch ( IndeterminateConfigurationException | RegistryException e )
  692. {
  693. if ( oldCfg != null )
  694. {
  695. getProvider( repositoryType ).updateManagedInstance( (EditableManagedRepository) repo, oldCfg );
  696. }
  697. log.error( "Could not save the configuration for repository {}: {}", id, e.getMessage( ), e );
  698. throw new RepositoryException( "Could not save the configuration for repository " + id + ": " + e.getMessage( ) );
  699. }
  700. return repo;
  701. }
  702. finally
  703. {
  704. rwLock.writeLock( ).unlock( );
  705. }
  706. }
  707. /**
  708. * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
  709. * the configuration is not saved.
  710. *
  711. * @param managedRepositoryConfiguration the new or changed managed repository configuration
  712. * @param configuration the configuration object (may be <code>null</code>)
  713. * @return the new or updated repository
  714. * @throws RepositoryException if the configuration cannot be saved or updated
  715. */
  716. @Override
  717. public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration ) throws RepositoryException
  718. {
  719. rwLock.writeLock( ).lock( );
  720. try
  721. {
  722. final String id = managedRepositoryConfiguration.getId( );
  723. final RepositoryType repoType = RepositoryType.valueOf( managedRepositoryConfiguration.getType( ) );
  724. ManagedRepository repo;
  725. boolean registeredNew = false;
  726. repo = managedRepositories.get( id );
  727. if ( repo != null && repo.isOpen( ) )
  728. {
  729. if ( repo instanceof EditableManagedRepository )
  730. {
  731. getProvider( repoType ).updateManagedInstance( (EditableManagedRepository) repo, managedRepositoryConfiguration );
  732. }
  733. else
  734. {
  735. throw new RepositoryException( "The repository is not editable " + id );
  736. }
  737. }
  738. else
  739. {
  740. repo = getProvider( repoType ).createManagedInstance( managedRepositoryConfiguration );
  741. managedRepositories.put( id, repo );
  742. registeredNew = true;
  743. }
  744. updateRepositoryReferences( getProvider( repoType ), repo, managedRepositoryConfiguration, configuration );
  745. replaceOrAddRepositoryConfig( managedRepositoryConfiguration, configuration );
  746. if ( registeredNew )
  747. {
  748. pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, repo ) );
  749. }
  750. else
  751. {
  752. pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, repo ) );
  753. }
  754. return repo;
  755. }
  756. finally
  757. {
  758. rwLock.writeLock( ).unlock( );
  759. }
  760. }
  761. /**
  762. * Adds a new repository group to the current list, or replaces the repository group definition with
  763. * the same id, if it exists already.
  764. * The change is saved to the configuration immediately.
  765. *
  766. * @param repositoryGroup the new repository group.
  767. * @throws RepositoryException if the new repository group could not be saved to the configuration.
  768. */
  769. @Override
  770. public RepositoryGroup putRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
  771. {
  772. rwLock.writeLock( ).lock( );
  773. try
  774. {
  775. if ( this.groupHandler == null )
  776. {
  777. throw new RepositoryException( "Fatal error. RepositoryGroupHandler not registered!" );
  778. }
  779. return this.groupHandler.put( repositoryGroup );
  780. }
  781. finally
  782. {
  783. rwLock.writeLock( ).unlock( );
  784. }
  785. }
  786. /**
  787. * Adds a new repository group or updates the repository with the same id, if it exists already.
  788. * The configuration is saved immediately.
  789. *
  790. * @param repositoryGroupConfiguration the repository configuration
  791. * @return the updated or created repository
  792. * @throws RepositoryException if an error occurs, or the configuration is not valid.
  793. */
  794. @Override
  795. public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException
  796. {
  797. rwLock.writeLock( ).lock( );
  798. try
  799. {
  800. return groupHandler.put( repositoryGroupConfiguration );
  801. }
  802. finally
  803. {
  804. rwLock.writeLock( ).unlock( );
  805. }
  806. }
  807. @Override
  808. public CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> putRepositoryGroupAndValidate( RepositoryGroupConfiguration repositoryGroupConfiguration )
  809. throws RepositoryException
  810. {
  811. rwLock.writeLock( ).lock( );
  812. try
  813. {
  814. return groupHandler.putWithCheck( repositoryGroupConfiguration, groupHandler.getValidator() );
  815. }
  816. finally
  817. {
  818. rwLock.writeLock( ).unlock( );
  819. }
  820. }
  821. /**
  822. * Adds a new repository group or updates the repository group with the same id. The given configuration object is updated, but
  823. * the configuration is not saved.
  824. *
  825. * @param repositoryGroupConfiguration The configuration of the new or changed repository group.
  826. * @param configuration The configuration object. If it is <code>null</code>, the configuration is not saved.
  827. * @return The new or updated repository group
  828. * @throws RepositoryException if the configuration cannot be saved or updated
  829. */
  830. @Override
  831. public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException
  832. {
  833. rwLock.writeLock( ).lock( );
  834. try
  835. {
  836. return groupHandler.put( repositoryGroupConfiguration, configuration );
  837. }
  838. finally
  839. {
  840. rwLock.writeLock( ).unlock( );
  841. }
  842. }
  843. private void replaceOrAddRepositoryConfig( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration )
  844. {
  845. if ( configuration != null )
  846. {
  847. ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( managedRepositoryConfiguration.getId( ) );
  848. if ( oldCfg != null )
  849. {
  850. configuration.removeManagedRepository( oldCfg );
  851. }
  852. configuration.addManagedRepository( managedRepositoryConfiguration );
  853. }
  854. }
  855. private void replaceOrAddRepositoryConfig( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration )
  856. {
  857. if ( configuration != null )
  858. {
  859. RemoteRepositoryConfiguration oldCfg = configuration.findRemoteRepositoryById( remoteRepositoryConfiguration.getId( ) );
  860. if ( oldCfg != null )
  861. {
  862. configuration.removeRemoteRepository( oldCfg );
  863. }
  864. configuration.addRemoteRepository( remoteRepositoryConfiguration );
  865. }
  866. }
  867. private void replaceOrAddRepositoryConfig( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration )
  868. {
  869. RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById( repositoryGroupConfiguration.getId( ) );
  870. if ( oldCfg != null )
  871. {
  872. configuration.removeRepositoryGroup( oldCfg );
  873. }
  874. configuration.addRepositoryGroup( repositoryGroupConfiguration );
  875. }
  876. @Override
  877. public RemoteRepository putRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException
  878. {
  879. rwLock.writeLock( ).lock( );
  880. try
  881. {
  882. final String id = remoteRepository.getId( );
  883. if ( managedRepositories.containsKey( id ) )
  884. {
  885. throw new RepositoryException( "There exists a managed repository with id " + id + ". Could not update with remote repository." );
  886. }
  887. RemoteRepository originRepo = remoteRepositories.put( id, remoteRepository );
  888. RemoteRepositoryConfiguration oldCfg = null;
  889. RemoteRepositoryConfiguration newCfg;
  890. try
  891. {
  892. if ( originRepo != null && originRepo != remoteRepository )
  893. {
  894. originRepo.close( );
  895. }
  896. final RepositoryProvider provider = getProvider( remoteRepository.getType( ) );
  897. newCfg = provider.getRemoteConfiguration( remoteRepository );
  898. updateRepositoryReferences( provider, remoteRepository, newCfg, configuration );
  899. oldCfg = configuration.findRemoteRepositoryById( id );
  900. if ( oldCfg != null )
  901. {
  902. configuration.removeRemoteRepository( oldCfg );
  903. }
  904. configuration.addRemoteRepository( newCfg );
  905. if ( remoteRepository != originRepo )
  906. {
  907. pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, remoteRepository ) );
  908. }
  909. else
  910. {
  911. pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, remoteRepository ) );
  912. }
  913. return remoteRepository;
  914. }
  915. catch ( Exception e )
  916. {
  917. // Rollback
  918. if ( originRepo != null )
  919. {
  920. remoteRepositories.put( id, originRepo );
  921. }
  922. else
  923. {
  924. remoteRepositories.remove( id );
  925. }
  926. if ( oldCfg != null )
  927. {
  928. RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( id );
  929. if ( cfg != null )
  930. {
  931. configuration.removeRemoteRepository( cfg );
  932. configuration.addRemoteRepository( oldCfg );
  933. }
  934. }
  935. log.error( "Error while adding remote repository {}", e.getMessage( ), e );
  936. throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ) );
  937. }
  938. }
  939. finally
  940. {
  941. rwLock.writeLock( ).unlock( );
  942. }
  943. }
  944. /**
  945. * Adds a remote repository, or overwrites the repository definition with the same id, if it exists already.
  946. * The modification is saved to the configuration immediately.
  947. *
  948. * @param remoteRepository the remote repository to add
  949. * @throws RepositoryException if an error occurs during configuration save
  950. */
  951. @Override
  952. public RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException
  953. {
  954. rwLock.writeLock( ).lock( );
  955. try
  956. {
  957. Configuration configuration = configurationHandler.getBaseConfiguration( );
  958. try
  959. {
  960. RemoteRepository repo = putRepository( remoteRepository, configuration );
  961. saveConfiguration( configuration );
  962. return repo;
  963. }
  964. catch ( RegistryException | IndeterminateConfigurationException e )
  965. {
  966. log.error( "Error while saving remote repository {}", e.getMessage( ), e );
  967. throw new RepositoryException( "Could not save the configuration" + ( e.getMessage( ) == null ? "" : ": " + e.getMessage( ) ) );
  968. }
  969. }
  970. finally
  971. {
  972. rwLock.writeLock( ).unlock( );
  973. }
  974. }
  975. /**
  976. * Adds a new repository or updates the repository with the same id, if it exists already.
  977. * The configuration is saved immediately.
  978. *
  979. * @param remoteRepositoryConfiguration the repository configuration
  980. * @return the updated or created repository
  981. * @throws RepositoryException if an error occurs, or the configuration is not valid.
  982. */
  983. @Override
  984. public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration ) throws RepositoryException
  985. {
  986. rwLock.writeLock( ).lock( );
  987. try
  988. {
  989. final String id = remoteRepositoryConfiguration.getId( );
  990. final RepositoryType repositoryType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType( ) );
  991. Configuration configuration = configurationHandler.getBaseConfiguration( );
  992. RemoteRepository repo = remoteRepositories.get( id );
  993. RemoteRepositoryConfiguration oldCfg = repo != null ? getProvider( repositoryType ).getRemoteConfiguration( repo ) : null;
  994. repo = putRepository( remoteRepositoryConfiguration, configuration );
  995. try
  996. {
  997. saveConfiguration( configuration );
  998. }
  999. catch ( IndeterminateConfigurationException | RegistryException e )
  1000. {
  1001. if ( oldCfg != null )
  1002. {
  1003. getProvider( repositoryType ).updateRemoteInstance( (EditableRemoteRepository) repo, oldCfg );
  1004. }
  1005. log.error( "Could not save the configuration for repository {}: {}", id, e.getMessage( ), e );
  1006. throw new RepositoryException( "Could not save the configuration for repository " + id + ": " + e.getMessage( ) );
  1007. }
  1008. return repo;
  1009. }
  1010. finally
  1011. {
  1012. rwLock.writeLock( ).unlock( );
  1013. }
  1014. }
  1015. /**
  1016. * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
  1017. * the configuration is not saved.
  1018. *
  1019. * @param remoteRepositoryConfiguration the new or changed repository configuration
  1020. * @param configuration the configuration object
  1021. * @return the new or updated repository
  1022. * @throws RepositoryException if the configuration cannot be saved or updated
  1023. */
  1024. @Override
  1025. @SuppressWarnings( "unchecked" )
  1026. public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration ) throws RepositoryException
  1027. {
  1028. rwLock.writeLock( ).lock( );
  1029. try
  1030. {
  1031. final String id = remoteRepositoryConfiguration.getId( );
  1032. final RepositoryType repoType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType( ) );
  1033. RemoteRepository repo;
  1034. boolean registeredNew = false;
  1035. repo = remoteRepositories.get( id );
  1036. if ( repo != null && repo.isOpen( ) )
  1037. {
  1038. if ( repo instanceof EditableRemoteRepository )
  1039. {
  1040. getProvider( repoType ).updateRemoteInstance( (EditableRemoteRepository) repo, remoteRepositoryConfiguration );
  1041. }
  1042. else
  1043. {
  1044. throw new RepositoryException( "The repository is not editable " + id );
  1045. }
  1046. }
  1047. else
  1048. {
  1049. repo = getProvider( repoType ).createRemoteInstance( remoteRepositoryConfiguration );
  1050. remoteRepositories.put( id, repo );
  1051. registeredNew = true;
  1052. }
  1053. updateRepositoryReferences( getProvider( repoType ), repo, remoteRepositoryConfiguration, configuration );
  1054. replaceOrAddRepositoryConfig( remoteRepositoryConfiguration, configuration );
  1055. if ( registeredNew )
  1056. {
  1057. pushEvent( new LifecycleEvent( LifecycleEvent.REGISTERED, this, repo ) );
  1058. }
  1059. else
  1060. {
  1061. pushEvent( new LifecycleEvent( LifecycleEvent.UPDATED, this, repo ) );
  1062. }
  1063. return repo;
  1064. }
  1065. finally
  1066. {
  1067. rwLock.writeLock( ).unlock( );
  1068. }
  1069. }
  1070. @Override
  1071. public void removeRepository( String repoId ) throws RepositoryException
  1072. {
  1073. Repository repo = getRepository( repoId );
  1074. if ( repo != null )
  1075. {
  1076. removeRepository( repo );
  1077. }
  1078. }
  1079. @Override
  1080. public void removeRepository( Repository repo ) throws RepositoryException
  1081. {
  1082. if ( repo == null )
  1083. {
  1084. log.warn( "Trying to remove null repository" );
  1085. return;
  1086. }
  1087. if ( repo instanceof RemoteRepository )
  1088. {
  1089. removeRepository( (RemoteRepository) repo );
  1090. }
  1091. else if ( repo instanceof ManagedRepository )
  1092. {
  1093. removeRepository( (ManagedRepository) repo );
  1094. }
  1095. else if ( repo instanceof RepositoryGroup )
  1096. {
  1097. removeRepositoryGroup( (RepositoryGroup) repo );
  1098. }
  1099. else
  1100. {
  1101. throw new RepositoryException( "Repository type not known: " + repo.getClass( ) );
  1102. }
  1103. }
  1104. /**
  1105. * Removes a managed repository from the registry and configuration, if it exists.
  1106. * The change is saved to the configuration immediately.
  1107. *
  1108. * @param managedRepository the managed repository to remove
  1109. * @throws RepositoryException if a error occurs during configuration save
  1110. */
  1111. @Override
  1112. public void removeRepository( ManagedRepository managedRepository ) throws RepositoryException
  1113. {
  1114. if ( managedRepository == null )
  1115. {
  1116. return;
  1117. }
  1118. final String id = managedRepository.getId( );
  1119. ManagedRepository repo = getManagedRepository( id );
  1120. if ( repo != null )
  1121. {
  1122. rwLock.writeLock( ).lock( );
  1123. try
  1124. {
  1125. repo = managedRepositories.remove( id );
  1126. if ( repo != null )
  1127. {
  1128. repo.close( );
  1129. this.groupHandler.removeRepositoryFromGroups( repo );
  1130. Configuration configuration = configurationHandler.getBaseConfiguration( );
  1131. ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById( id );
  1132. if ( cfg != null )
  1133. {
  1134. configuration.removeManagedRepository( cfg );
  1135. }
  1136. saveConfiguration( configuration );
  1137. }
  1138. pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
  1139. }
  1140. catch ( RegistryException | IndeterminateConfigurationException e )
  1141. {
  1142. // Rollback
  1143. log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
  1144. managedRepositories.put( repo.getId( ), repo );
  1145. throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
  1146. }
  1147. finally
  1148. {
  1149. rwLock.writeLock( ).unlock( );
  1150. }
  1151. }
  1152. }
  1153. @Override
  1154. public void removeRepository( ManagedRepository managedRepository, Configuration configuration ) throws RepositoryException
  1155. {
  1156. if ( managedRepository == null )
  1157. {
  1158. return;
  1159. }
  1160. final String id = managedRepository.getId( );
  1161. ManagedRepository repo = getManagedRepository( id );
  1162. if ( repo != null )
  1163. {
  1164. rwLock.writeLock( ).lock( );
  1165. try
  1166. {
  1167. repo = managedRepositories.remove( id );
  1168. if ( repo != null )
  1169. {
  1170. repo.close( );
  1171. this.groupHandler.removeRepositoryFromGroups( repo );
  1172. ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById( id );
  1173. if ( cfg != null )
  1174. {
  1175. configuration.removeManagedRepository( cfg );
  1176. }
  1177. }
  1178. pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
  1179. }
  1180. finally
  1181. {
  1182. rwLock.writeLock( ).unlock( );
  1183. }
  1184. }
  1185. }
  1186. /**
  1187. * Removes a repository group from the registry and configuration, if it exists.
  1188. * The change is saved to the configuration immediately.
  1189. *
  1190. * @param repositoryGroup the repository group to remove
  1191. * @throws RepositoryException if a error occurs during configuration save
  1192. */
  1193. @Override
  1194. public void removeRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
  1195. {
  1196. if ( repositoryGroup == null )
  1197. {
  1198. return;
  1199. }
  1200. final String id = repositoryGroup.getId( );
  1201. if ( groupHandler.has( id ) )
  1202. {
  1203. rwLock.writeLock( ).lock( );
  1204. try
  1205. {
  1206. groupHandler.remove( id );
  1207. }
  1208. finally
  1209. {
  1210. rwLock.writeLock( ).unlock( );
  1211. }
  1212. }
  1213. }
  1214. @Override
  1215. public void removeRepositoryGroup( RepositoryGroup repositoryGroup, Configuration configuration ) throws RepositoryException
  1216. {
  1217. if ( repositoryGroup == null )
  1218. {
  1219. return;
  1220. }
  1221. final String id = repositoryGroup.getId( );
  1222. if ( groupHandler.has( id ) )
  1223. {
  1224. rwLock.writeLock( ).lock( );
  1225. try
  1226. {
  1227. groupHandler.remove( id, configuration );
  1228. }
  1229. finally
  1230. {
  1231. rwLock.writeLock( ).unlock( );
  1232. }
  1233. }
  1234. }
  1235. private void doRemoveRepo( RemoteRepository repo, Configuration configuration )
  1236. {
  1237. repo.close( );
  1238. RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( repo.getId( ) );
  1239. if ( cfg != null )
  1240. {
  1241. configuration.removeRemoteRepository( cfg );
  1242. }
  1243. List<ProxyConnectorConfiguration> proxyConnectors = new ArrayList<>( configuration.getProxyConnectors( ) );
  1244. for ( ProxyConnectorConfiguration proxyConnector : proxyConnectors )
  1245. {
  1246. if ( StringUtils.equals( proxyConnector.getTargetRepoId( ), repo.getId( ) ) )
  1247. {
  1248. configuration.removeProxyConnector( proxyConnector );
  1249. }
  1250. }
  1251. }
  1252. /**
  1253. * Removes the remote repository from the registry and configuration.
  1254. * The change is saved to the configuration immediately.
  1255. *
  1256. * @param remoteRepository the remote repository to remove
  1257. * @throws RepositoryException if a error occurs during configuration save
  1258. */
  1259. @Override
  1260. public void removeRepository( RemoteRepository remoteRepository ) throws RepositoryException
  1261. {
  1262. if ( remoteRepository == null )
  1263. {
  1264. return;
  1265. }
  1266. final String id = remoteRepository.getId( );
  1267. RemoteRepository repo = getRemoteRepository( id );
  1268. if ( repo != null )
  1269. {
  1270. rwLock.writeLock( ).lock( );
  1271. try
  1272. {
  1273. repo = remoteRepositories.remove( id );
  1274. if ( repo != null )
  1275. {
  1276. Configuration configuration = configurationHandler.getBaseConfiguration( );
  1277. doRemoveRepo( repo, configuration );
  1278. saveConfiguration( configuration );
  1279. }
  1280. pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
  1281. }
  1282. catch ( RegistryException | IndeterminateConfigurationException e )
  1283. {
  1284. // Rollback
  1285. log.error( "Could not save config after repository removal: {}", e.getMessage( ), e );
  1286. remoteRepositories.put( repo.getId( ), repo );
  1287. throw new RepositoryException( "Could not save configuration after repository removal: " + e.getMessage( ) );
  1288. }
  1289. finally
  1290. {
  1291. rwLock.writeLock( ).unlock( );
  1292. }
  1293. }
  1294. }
  1295. @Override
  1296. public void removeRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException
  1297. {
  1298. if ( remoteRepository == null )
  1299. {
  1300. return;
  1301. }
  1302. final String id = remoteRepository.getId( );
  1303. RemoteRepository repo = getRemoteRepository( id );
  1304. if ( repo != null )
  1305. {
  1306. rwLock.writeLock( ).lock( );
  1307. try
  1308. {
  1309. repo = remoteRepositories.remove( id );
  1310. if ( repo != null )
  1311. {
  1312. doRemoveRepo( repo, configuration );
  1313. }
  1314. pushEvent( new LifecycleEvent( LifecycleEvent.UNREGISTERED, this, repo ) );
  1315. }
  1316. finally
  1317. {
  1318. rwLock.writeLock( ).unlock( );
  1319. }
  1320. }
  1321. }
  1322. /**
  1323. * Reloads the registry from the configuration.
  1324. */
  1325. @Override
  1326. public void reload( )
  1327. {
  1328. initialize( );
  1329. }
  1330. /**
  1331. * Resets the indexing context of a given repository.
  1332. *
  1333. * @param repository The repository
  1334. * @throws IndexUpdateFailedException If the index could not be resetted.
  1335. */
  1336. @Override
  1337. public void resetIndexingContext( Repository repository ) throws IndexUpdateFailedException
  1338. {
  1339. if ( repository.hasIndex( ) && repository instanceof EditableRepository )
  1340. {
  1341. EditableRepository eRepo = (EditableRepository) repository;
  1342. ArchivaIndexingContext newCtx = getIndexManager( repository.getType( ) ).reset( repository.getIndexingContext( ) );
  1343. eRepo.setIndexingContext( newCtx );
  1344. }
  1345. }
  1346. /**
  1347. * Creates a new repository instance with the same settings as this one. The cloned repository is not
  1348. * registered or saved to the configuration.
  1349. *
  1350. * @param repo The origin repository
  1351. * @return The cloned repository.
  1352. */
  1353. public ManagedRepository clone( ManagedRepository repo, String newId ) throws RepositoryException
  1354. {
  1355. if ( managedRepositories.containsKey( newId ) || remoteRepositories.containsKey( newId ) )
  1356. {
  1357. throw new RepositoryException( "The given id exists already " + newId );
  1358. }
  1359. RepositoryProvider provider = getProvider( repo.getType( ) );
  1360. ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration( repo );
  1361. cfg.setId( newId );
  1362. ManagedRepository cloned = provider.createManagedInstance( cfg );
  1363. cloned.registerEventHandler( RepositoryEvent.ANY, this );
  1364. return cloned;
  1365. }
  1366. @Override
  1367. public <T extends Repository> T clone( T repo, String newId ) throws RepositoryException
  1368. {
  1369. if ( repo instanceof RemoteRepository )
  1370. {
  1371. return (T) this.clone( (RemoteRepository) repo, newId );
  1372. }
  1373. else if ( repo instanceof ManagedRepository )
  1374. {
  1375. return (T) this.clone( (ManagedRepository) repo, newId );
  1376. }
  1377. else
  1378. {
  1379. throw new RepositoryException( "This repository class is not supported " + repo.getClass( ).getName( ) );
  1380. }
  1381. }
  1382. /**
  1383. * Creates a new repository instance with the same settings as this one. The cloned repository is not
  1384. * registered or saved to the configuration.
  1385. *
  1386. * @param repo The origin repository
  1387. * @return The cloned repository.
  1388. */
  1389. public RemoteRepository clone( RemoteRepository repo, String newId ) throws RepositoryException
  1390. {
  1391. if ( managedRepositories.containsKey( newId ) || remoteRepositories.containsKey( newId ) )
  1392. {
  1393. throw new RepositoryException( "The given id exists already " + newId );
  1394. }
  1395. RepositoryProvider provider = getProvider( repo.getType( ) );
  1396. RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration( repo );
  1397. cfg.setId( newId );
  1398. RemoteRepository cloned = provider.createRemoteInstance( cfg );
  1399. cloned.registerEventHandler( RepositoryEvent.ANY, this );
  1400. return cloned;
  1401. }
  1402. @Override
  1403. public Repository getRepositoryOfAsset( StorageAsset asset )
  1404. {
  1405. if ( asset instanceof Repository )
  1406. {
  1407. return (Repository) asset;
  1408. }
  1409. else
  1410. {
  1411. return getRepositories( ).stream( ).filter( r -> r.getRoot( )
  1412. .getStorage( ).equals( asset.getStorage( ) ) ).findFirst( ).orElse( null );
  1413. }
  1414. }
  1415. @Override
  1416. public <R extends Repository> ValidationResponse<R> validateRepository( R repository )
  1417. {
  1418. Map<String, List<ValidationError>> errorMap = this.validators.stream( )
  1419. .filter( ( validator ) -> validator.getType( ).equals( RepositoryType.ALL ) || repository.getType( ).equals( validator.getType( ) ) )
  1420. .filter( val -> val.isFlavour( repository.getClass() ))
  1421. .flatMap( validator -> ((RepositoryValidator<R>)validator).apply( repository ).getResult().entrySet( ).stream( ) )
  1422. .collect( Collectors.toMap(
  1423. entry -> entry.getKey( ),
  1424. entry -> entry.getValue( ),
  1425. ( list1, list2 ) -> ListUtils.union( list1, list2 )
  1426. ) );
  1427. return new ValidationResponse( repository, errorMap );
  1428. }
  1429. @Override
  1430. public <R extends Repository> ValidationResponse<R> validateRepositoryForUpdate( R repository )
  1431. {
  1432. Map<String, List<ValidationError>> errorMap = this.validators.stream( )
  1433. .filter( ( validator ) -> validator.getType( ).equals( RepositoryType.ALL ) || repository.getType( ).equals( validator.getType( ) ) )
  1434. .filter( val -> val.isFlavour( repository.getClass() ))
  1435. .flatMap( validator -> ((RepositoryValidator<R>)validator).applyForUpdate( repository ).getResult().entrySet( ).stream( ) )
  1436. .collect( Collectors.toMap(
  1437. entry -> entry.getKey( ),
  1438. entry -> entry.getValue( ),
  1439. ( list1, list2 ) -> ListUtils.union( list1, list2 )
  1440. ) );
  1441. return new ValidationResponse( repository, errorMap );
  1442. }
  1443. @Override
  1444. public void configurationEvent( ConfigurationEvent event )
  1445. {
  1446. // We ignore the event, if the save was triggered by ourself
  1447. if ( !ConfigurationHandler.REGISTRY_EVENT_TAG.equals( event.getTag( ) ) )
  1448. {
  1449. reload( );
  1450. }
  1451. }
  1452. @Override
  1453. public <T extends Event> void registerEventHandler( EventType<T> type, EventHandler<? super T> eventHandler )
  1454. {
  1455. eventManager.registerEventHandler( type, eventHandler );
  1456. }
  1457. @Override
  1458. public <T extends Event> void unregisterEventHandler( EventType<T> type, EventHandler<? super T> eventHandler )
  1459. {
  1460. eventManager.unregisterEventHandler( type, eventHandler );
  1461. }
  1462. @Override
  1463. public void handle( Event event )
  1464. {
  1465. // To avoid event cycles:
  1466. if ( sameOriginator( event ) )
  1467. {
  1468. return;
  1469. }
  1470. if ( event instanceof RepositoryIndexEvent )
  1471. {
  1472. handleIndexCreationEvent( (RepositoryIndexEvent) event );
  1473. }
  1474. // We propagate all events to our listeners, but with context of repository registry
  1475. pushEvent( event );
  1476. }
  1477. private void handleIndexCreationEvent( RepositoryIndexEvent event )
  1478. {
  1479. RepositoryIndexEvent idxEvent = event;
  1480. EditableRepository repo = (EditableRepository) idxEvent.getRepository( );
  1481. if ( repo != null )
  1482. {
  1483. ArchivaIndexManager idxmgr = getIndexManager( repo.getType( ) );
  1484. if ( repo.getIndexingContext( ) != null )
  1485. {
  1486. try
  1487. {
  1488. ArchivaIndexingContext newCtx = idxmgr.move( repo.getIndexingContext( ), repo );
  1489. repo.setIndexingContext( newCtx );
  1490. idxmgr.updateLocalIndexPath( repo );
  1491. }
  1492. catch ( IndexCreationFailedException e )
  1493. {
  1494. log.error( "Could not move index to new directory: '{}'", e.getMessage( ), e );
  1495. }
  1496. }
  1497. else
  1498. {
  1499. try
  1500. {
  1501. ArchivaIndexingContext context = idxmgr.createContext( repo );
  1502. repo.setIndexingContext( context );
  1503. idxmgr.updateLocalIndexPath( repo );
  1504. }
  1505. catch ( IndexCreationFailedException e )
  1506. {
  1507. log.error( "Could not create index: '{}'", e.getMessage( ), e );
  1508. }
  1509. }
  1510. }
  1511. }
  1512. private boolean sameOriginator( Event event )
  1513. {
  1514. if ( event.getSource( ) == this )
  1515. {
  1516. return true;
  1517. }
  1518. else if ( event.hasPreviousEvent( ) )
  1519. {
  1520. return sameOriginator( event.getPreviousEvent( ) );
  1521. }
  1522. else
  1523. {
  1524. return false;
  1525. }
  1526. }
  1527. private void pushEvent( Event event )
  1528. {
  1529. eventManager.fireEvent( event );
  1530. }
  1531. }