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.

RepositoryRegistry.java 42KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. package org.apache.archiva.repository;
  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.configuration.ArchivaConfiguration;
  21. import org.apache.archiva.configuration.Configuration;
  22. import org.apache.archiva.configuration.ConfigurationEvent;
  23. import org.apache.archiva.configuration.ConfigurationListener;
  24. import org.apache.archiva.configuration.IndeterminateConfigurationException;
  25. import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
  26. import org.apache.archiva.configuration.ProxyConnectorConfiguration;
  27. import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
  28. import org.apache.archiva.indexer.ArchivaIndexManager;
  29. import org.apache.archiva.indexer.ArchivaIndexingContext;
  30. import org.apache.archiva.indexer.IndexCreationFailedException;
  31. import org.apache.archiva.indexer.IndexManagerFactory;
  32. import org.apache.archiva.indexer.IndexUpdateFailedException;
  33. import org.apache.archiva.redback.components.registry.RegistryException;
  34. import org.apache.archiva.repository.features.IndexCreationEvent;
  35. import org.apache.archiva.repository.features.IndexCreationFeature;
  36. import org.apache.archiva.repository.features.StagingRepositoryFeature;
  37. import org.apache.commons.lang.StringUtils;
  38. import org.slf4j.Logger;
  39. import org.slf4j.LoggerFactory;
  40. import org.springframework.stereotype.Service;
  41. import javax.annotation.PostConstruct;
  42. import javax.annotation.PreDestroy;
  43. import javax.inject.Inject;
  44. import javax.inject.Named;
  45. import java.util.ArrayList;
  46. import java.util.Collection;
  47. import java.util.Collections;
  48. import java.util.HashMap;
  49. import java.util.LinkedHashMap;
  50. import java.util.List;
  51. import java.util.Map;
  52. import java.util.concurrent.locks.ReentrantReadWriteLock;
  53. import java.util.stream.Collectors;
  54. import java.util.stream.Stream;
  55. /**
  56. * Registry for repositories. This is the central entry point for repositories. It provides methods for
  57. * retrieving, adding and removing repositories.
  58. *
  59. * The modification methods addXX and removeXX persist the changes immediately to the configuration. If the
  60. * configuration save fails the changes are rolled back.
  61. *
  62. * TODO: Audit events should be sent, but we don't want dependency to the repsitory-metadata-api
  63. */
  64. @Service( "repositoryRegistry" )
  65. public class RepositoryRegistry implements ConfigurationListener, RepositoryEventHandler, RepositoryEventListener {
  66. private static final Logger log = LoggerFactory.getLogger( RepositoryRegistry.class );
  67. /**
  68. * We inject all repository providers
  69. */
  70. @Inject
  71. List<RepositoryProvider> repositoryProviders;
  72. @Inject
  73. IndexManagerFactory indexManagerFactory;
  74. @Inject
  75. ArchivaConfiguration archivaConfiguration;
  76. @Inject
  77. @Named("repositoryContentFactory#default")
  78. RepositoryContentFactory repositoryContentFactory;
  79. private List<RepositoryEventListener> listeners = new ArrayList<>();
  80. private Map<String, ManagedRepository> managedRepositories = new HashMap<>( );
  81. private Map<String, ManagedRepository> uManagedRepository = Collections.unmodifiableMap( managedRepositories );
  82. private Map<String, RemoteRepository> remoteRepositories = new HashMap<>( );
  83. private Map<String, RemoteRepository> uRemoteRepositories = Collections.unmodifiableMap( remoteRepositories );
  84. private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock( );
  85. public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration) {
  86. this.archivaConfiguration = archivaConfiguration;
  87. }
  88. @PostConstruct
  89. private void initialize( )
  90. {
  91. rwLock.writeLock( ).lock( );
  92. try
  93. {
  94. log.debug("Initializing repository registry");
  95. for(ManagedRepository rep : managedRepositories.values()) {
  96. rep.close();
  97. }
  98. managedRepositories.clear( );
  99. managedRepositories.putAll( getManagedRepositoriesFromConfig( ) );
  100. for (RemoteRepository repo : remoteRepositories.values()) {
  101. repo.close();
  102. }
  103. remoteRepositories.clear( );
  104. remoteRepositories.putAll( getRemoteRepositoriesFromConfig( ) );
  105. // archivaConfiguration.addChangeListener(this);
  106. archivaConfiguration.addListener(this);
  107. }
  108. finally
  109. {
  110. rwLock.writeLock( ).unlock( );
  111. }
  112. }
  113. @PreDestroy
  114. public void destroy() {
  115. for(ManagedRepository rep : managedRepositories.values()) {
  116. rep.close();
  117. }
  118. for (RemoteRepository repo : remoteRepositories.values()) {
  119. repo.close();
  120. }
  121. }
  122. private Map<RepositoryType, RepositoryProvider> createProviderMap( )
  123. {
  124. Map<RepositoryType, RepositoryProvider> map = new HashMap<>( );
  125. if ( repositoryProviders != null )
  126. {
  127. for ( RepositoryProvider provider : repositoryProviders )
  128. {
  129. for ( RepositoryType type : provider.provides( ) )
  130. {
  131. map.put( type, provider );
  132. }
  133. }
  134. }
  135. return map;
  136. }
  137. private RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
  138. {
  139. return repositoryProviders.stream( ).filter( repositoryProvider -> repositoryProvider.provides( ).contains( type ) ).findFirst( ).orElseThrow( ( ) -> new RepositoryException( "Repository type cannot be handled: " + type ) );
  140. }
  141. private Map<String, ManagedRepository> getManagedRepositoriesFromConfig( )
  142. {
  143. try
  144. {
  145. List<ManagedRepositoryConfiguration> managedRepoConfigs =
  146. getArchivaConfiguration( ).getConfiguration( ).getManagedRepositories( );
  147. if ( managedRepoConfigs == null )
  148. {
  149. return Collections.emptyMap();
  150. }
  151. Map<String, ManagedRepository> managedRepos = new LinkedHashMap<>( managedRepoConfigs.size( ) );
  152. Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap( );
  153. for ( ManagedRepositoryConfiguration repoConfig : managedRepoConfigs )
  154. {
  155. RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
  156. if ( providerMap.containsKey( repositoryType ) )
  157. {
  158. try
  159. {
  160. ManagedRepository repo = createNewManagedRepository( providerMap.get( repositoryType ), repoConfig );
  161. managedRepos.put( repo.getId( ), repo );
  162. }
  163. catch ( Exception e )
  164. {
  165. log.error( "Could not create managed repository {}: {}", repoConfig.getId( ), e.getMessage( ), e );
  166. }
  167. }
  168. }
  169. return managedRepos;
  170. } catch (Throwable e) {
  171. log.error("Could not initialize repositories from config: {}",e.getMessage(), e );
  172. //noinspection unchecked
  173. return Collections.emptyMap();
  174. }
  175. }
  176. private ManagedRepository createNewManagedRepository( RepositoryProvider provider, ManagedRepositoryConfiguration cfg ) throws RepositoryException
  177. {
  178. log.debug("Creating repo {}", cfg.getId());
  179. ManagedRepository repo = provider.createManagedInstance( cfg );
  180. repo.addListener(this);
  181. updateRepositoryReferences( provider, repo, cfg , null);
  182. return repo;
  183. }
  184. @SuppressWarnings( "unchecked" )
  185. private void updateRepositoryReferences(RepositoryProvider provider, ManagedRepository repo, ManagedRepositoryConfiguration cfg, Configuration configuration) throws RepositoryException
  186. {
  187. log.debug("Updating references of repo {}",repo.getId());
  188. if ( repo.supportsFeature( StagingRepositoryFeature.class ) )
  189. {
  190. StagingRepositoryFeature feature = repo.getFeature( StagingRepositoryFeature.class ).get( );
  191. if ( feature.isStageRepoNeeded( ) && feature.getStagingRepository() == null)
  192. {
  193. ManagedRepository stageRepo = getStagingRepository( provider, cfg, configuration);
  194. managedRepositories.put(stageRepo.getId(), stageRepo);
  195. feature.setStagingRepository( stageRepo );
  196. if (configuration!=null) {
  197. replaceOrAddRepositoryConfig( provider.getManagedConfiguration( stageRepo ), configuration );
  198. }
  199. }
  200. }
  201. if ( repo instanceof EditableManagedRepository)
  202. {
  203. EditableManagedRepository editableRepo = (EditableManagedRepository) repo;
  204. if (repo.getContent()==null) {
  205. editableRepo.setContent(repositoryContentFactory.getManagedRepositoryContent(repo));
  206. }
  207. log.debug("Index repo: "+repo.hasIndex());
  208. if (repo.hasIndex() && repo.getIndexingContext()==null) {
  209. log.debug("Creating indexing context for {}", repo.getId());
  210. createIndexingContext(editableRepo);
  211. }
  212. }
  213. }
  214. private ArchivaIndexManager getIndexManager(RepositoryType type) {
  215. return indexManagerFactory.getIndexManager(type);
  216. }
  217. private void createIndexingContext(EditableRepository editableRepo) throws RepositoryException {
  218. if (editableRepo.supportsFeature(IndexCreationFeature.class)) {
  219. ArchivaIndexManager idxManager = getIndexManager(editableRepo.getType());
  220. try {
  221. editableRepo.setIndexingContext(idxManager.createContext(editableRepo));
  222. idxManager.updateLocalIndexPath(editableRepo);
  223. } catch (IndexCreationFailedException e) {
  224. throw new RepositoryException("Could not create index for repository "+editableRepo.getId()+": "+e.getMessage(),e);
  225. }
  226. }
  227. }
  228. private ManagedRepository getStagingRepository(RepositoryProvider provider, ManagedRepositoryConfiguration baseRepoCfg, Configuration configuration) throws RepositoryException
  229. {
  230. ManagedRepository stageRepo = getManagedRepository( baseRepoCfg.getId( ) + StagingRepositoryFeature.STAGING_REPO_POSTFIX );
  231. if ( stageRepo == null )
  232. {
  233. stageRepo = provider.createStagingInstance( baseRepoCfg );
  234. if (stageRepo.supportsFeature(StagingRepositoryFeature.class)) {
  235. stageRepo.getFeature(StagingRepositoryFeature.class).get().setStageRepoNeeded(false);
  236. }
  237. ManagedRepositoryConfiguration stageCfg = provider.getManagedConfiguration( stageRepo );
  238. updateRepositoryReferences( provider, stageRepo, stageCfg, configuration);
  239. }
  240. return stageRepo;
  241. }
  242. private Map<String, RemoteRepository> getRemoteRepositoriesFromConfig( )
  243. {
  244. try
  245. {
  246. List<RemoteRepositoryConfiguration> remoteRepoConfigs =
  247. getArchivaConfiguration( ).getConfiguration( ).getRemoteRepositories( );
  248. if ( remoteRepoConfigs == null )
  249. {
  250. //noinspection unchecked
  251. return Collections.emptyMap();
  252. }
  253. Map<String, RemoteRepository> remoteRepos = new LinkedHashMap<>( remoteRepoConfigs.size( ) );
  254. Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap( );
  255. for ( RemoteRepositoryConfiguration repoConfig : remoteRepoConfigs )
  256. {
  257. RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
  258. if ( providerMap.containsKey( repositoryType ) )
  259. {
  260. RepositoryProvider provider = getProvider( repositoryType );
  261. try
  262. {
  263. RemoteRepository remoteRepository = createNewRemoteRepository( provider, repoConfig );
  264. remoteRepos.put( repoConfig.getId( ), remoteRepository);
  265. }
  266. catch ( Exception e )
  267. {
  268. log.error( "Could not create repository {} from config: {}", repoConfig.getId( ), e.getMessage( ), e );
  269. }
  270. }
  271. }
  272. return remoteRepos;
  273. } catch (Throwable e) {
  274. log.error("Could not initialize remote repositories from config: {}", e.getMessage(), e);
  275. //noinspection unchecked
  276. return Collections.emptyMap();
  277. }
  278. }
  279. private RemoteRepository createNewRemoteRepository( RepositoryProvider provider, RemoteRepositoryConfiguration cfg ) throws RepositoryException
  280. {
  281. log.debug("Creating remote repo {}", cfg.getId());
  282. RemoteRepository repo = provider.createRemoteInstance( cfg );
  283. repo.addListener(this);
  284. updateRepositoryReferences( provider, repo, cfg , null);
  285. return repo;
  286. }
  287. @SuppressWarnings( "unchecked" )
  288. private void updateRepositoryReferences( RepositoryProvider provider, RemoteRepository repo, RemoteRepositoryConfiguration cfg, Configuration configuration) throws RepositoryException
  289. {
  290. if ( repo instanceof EditableRemoteRepository && repo.getContent() == null)
  291. {
  292. EditableRemoteRepository editableRepo = (EditableRemoteRepository) repo;
  293. editableRepo.setContent( repositoryContentFactory.getRemoteRepositoryContent( repo ) );
  294. if (repo.supportsFeature(IndexCreationFeature.class) && repo.getIndexingContext()==null ) {
  295. createIndexingContext(editableRepo);
  296. }
  297. }
  298. }
  299. private ArchivaConfiguration getArchivaConfiguration( )
  300. {
  301. return this.archivaConfiguration;
  302. }
  303. /**
  304. * Returns all repositories that are registered. There is no defined order of the returned repositories.
  305. *
  306. * @return a list of managed and remote repositories
  307. */
  308. public Collection<Repository> getRepositories( )
  309. {
  310. rwLock.readLock( ).lock( );
  311. try
  312. {
  313. return Stream.concat( managedRepositories.values( ).stream( ), remoteRepositories.values( ).stream( ) ).collect( Collectors.toList( ) );
  314. }
  315. finally
  316. {
  317. rwLock.readLock( ).unlock( );
  318. }
  319. }
  320. /**
  321. * Returns only the managed repositories. There is no defined order of the returned repositories.
  322. *
  323. * @return a list of managed repositories
  324. */
  325. public Collection<ManagedRepository> getManagedRepositories( )
  326. {
  327. rwLock.readLock().lock();
  328. try
  329. {
  330. return uManagedRepository.values( );
  331. } finally
  332. {
  333. rwLock.readLock().unlock();
  334. }
  335. }
  336. /**
  337. * Returns only the remote repositories. There is no defined order of the returned repositories.
  338. *
  339. * @return a list of remote repositories
  340. */
  341. public Collection<RemoteRepository> getRemoteRepositories( )
  342. {
  343. rwLock.readLock().lock();
  344. try
  345. {
  346. return uRemoteRepositories.values( );
  347. } finally
  348. {
  349. rwLock.readLock().unlock();
  350. }
  351. }
  352. /**
  353. * Returns the repository with the given id. The returned repository may be a managed or remote repository.
  354. * It returns null, if no repository is registered with the given id.
  355. *
  356. * @param repoId the repository id
  357. * @return the repository if found, otherwise null
  358. */
  359. public Repository getRepository( String repoId )
  360. {
  361. rwLock.readLock( ).lock( );
  362. try
  363. {
  364. log.debug("getRepository {}", repoId);
  365. if ( managedRepositories.containsKey( repoId ) )
  366. {
  367. log.debug("Managed repo");
  368. return managedRepositories.get( repoId );
  369. }
  370. else
  371. {
  372. log.debug("Remote repo");
  373. return remoteRepositories.get( repoId );
  374. }
  375. }
  376. finally
  377. {
  378. rwLock.readLock( ).unlock( );
  379. }
  380. }
  381. /**
  382. * Convenience method, that returns the managed repository with the given id.
  383. * It returns null, if no managed repository is registered with this id.
  384. *
  385. * @param repoId the repository id
  386. * @return the managed repository if found, otherwise null
  387. */
  388. public ManagedRepository getManagedRepository( String repoId )
  389. {
  390. rwLock.readLock( ).lock( );
  391. try
  392. {
  393. return managedRepositories.get( repoId );
  394. }
  395. finally
  396. {
  397. rwLock.readLock( ).unlock( );
  398. }
  399. }
  400. /**
  401. * Convenience method, that returns the remote repository with the given id.
  402. * It returns null, if no remote repository is registered with this id.
  403. *
  404. * @param repoId the repository id
  405. * @return the remote repository if found, otherwise null
  406. */
  407. public RemoteRepository getRemoteRepository( String repoId )
  408. {
  409. rwLock.readLock( ).lock( );
  410. try
  411. {
  412. return remoteRepositories.get( repoId );
  413. }
  414. finally
  415. {
  416. rwLock.readLock( ).unlock( );
  417. }
  418. }
  419. /**
  420. * Adds a new repository to the current list, or replaces the repository definition with
  421. * the same id, if it exists already.
  422. * The change is saved to the configuration immediately.
  423. *
  424. * @param managedRepository the new repository.
  425. * @throws RepositoryException if the new repository could not be saved to the configuration.
  426. */
  427. public ManagedRepository putRepository( ManagedRepository managedRepository ) throws RepositoryException
  428. {
  429. rwLock.writeLock( ).lock( );
  430. try
  431. {
  432. final String id = managedRepository.getId();
  433. if (remoteRepositories.containsKey( id )) {
  434. throw new RepositoryException( "There exists a remote repository with id "+id+". Could not update with managed repository." );
  435. }
  436. ManagedRepository originRepo = managedRepositories.put( id, managedRepository );
  437. try
  438. {
  439. if (originRepo!=null) {
  440. originRepo.close();
  441. }
  442. RepositoryProvider provider = getProvider( managedRepository.getType() );
  443. ManagedRepositoryConfiguration newCfg = provider.getManagedConfiguration( managedRepository );
  444. Configuration configuration = getArchivaConfiguration( ).getConfiguration( );
  445. updateRepositoryReferences( provider, managedRepository, newCfg, configuration );
  446. ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( id );
  447. if (oldCfg!=null) {
  448. configuration.removeManagedRepository( oldCfg );
  449. }
  450. configuration.addManagedRepository( newCfg );
  451. getArchivaConfiguration( ).save( configuration );
  452. return managedRepository;
  453. }
  454. catch ( Exception e )
  455. {
  456. // Rollback
  457. if ( originRepo != null )
  458. {
  459. managedRepositories.put( id, originRepo );
  460. } else {
  461. managedRepositories.remove(id);
  462. }
  463. log.error("Exception during configuration update {}", e.getMessage(), e);
  464. throw new RepositoryException( "Could not save the configuration" + (e.getMessage( )==null?"":": "+e.getMessage()) );
  465. }
  466. }
  467. finally
  468. {
  469. rwLock.writeLock( ).unlock( );
  470. }
  471. }
  472. /**
  473. * Adds a new repository or updates the repository with the same id, if it exists already.
  474. * The configuration is saved immediately.
  475. *
  476. * @param managedRepositoryConfiguration the repository configuration
  477. * @return the updated or created repository
  478. * @throws RepositoryException if an error occurs, or the configuration is not valid.
  479. */
  480. public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration) throws RepositoryException
  481. {
  482. rwLock.writeLock( ).lock( );
  483. try
  484. {
  485. final String id = managedRepositoryConfiguration.getId();
  486. final RepositoryType repositoryType = RepositoryType.valueOf( managedRepositoryConfiguration.getType() );
  487. Configuration configuration = getArchivaConfiguration().getConfiguration();
  488. ManagedRepository repo = managedRepositories.get(id);
  489. ManagedRepositoryConfiguration oldCfg = repo!=null ? getProvider( repositoryType ).getManagedConfiguration( repo ) : null;
  490. repo = putRepository( managedRepositoryConfiguration, configuration );
  491. try
  492. {
  493. getArchivaConfiguration().save(configuration);
  494. }
  495. catch ( IndeterminateConfigurationException | RegistryException e )
  496. {
  497. if (oldCfg!=null) {
  498. getProvider( repositoryType ).updateManagedInstance( (EditableManagedRepository)repo, oldCfg );
  499. }
  500. log.error("Could not save the configuration for repository {}: {}", id, e.getMessage(),e );
  501. throw new RepositoryException( "Could not save the configuration for repository "+id+": "+e.getMessage() );
  502. }
  503. return repo;
  504. }
  505. finally
  506. {
  507. rwLock.writeLock( ).unlock( );
  508. }
  509. }
  510. /**
  511. * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
  512. * the configuration is not saved.
  513. *
  514. * @param managedRepositoryConfiguration the new or changed repository configuration
  515. * @param configuration the configuration object
  516. * @return the new or updated repository
  517. * @throws RepositoryException if the configuration cannot be saved or updated
  518. */
  519. @SuppressWarnings( "unchecked" )
  520. public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration) throws RepositoryException
  521. {
  522. rwLock.writeLock( ).lock( );
  523. try
  524. {
  525. final String id = managedRepositoryConfiguration.getId();
  526. final RepositoryType repoType = RepositoryType.valueOf( managedRepositoryConfiguration.getType() );
  527. ManagedRepository repo;
  528. if (managedRepositories.containsKey( id )) {
  529. repo = managedRepositories.get(id);
  530. if (repo instanceof EditableManagedRepository)
  531. {
  532. getProvider( repoType ).updateManagedInstance( (EditableManagedRepository) repo, managedRepositoryConfiguration );
  533. } else {
  534. throw new RepositoryException( "The repository is not editable "+id );
  535. }
  536. } else
  537. {
  538. repo = getProvider( repoType ).createManagedInstance( managedRepositoryConfiguration );
  539. repo.addListener(this);
  540. managedRepositories.put(id, repo);
  541. }
  542. updateRepositoryReferences( getProvider( repoType ), repo, managedRepositoryConfiguration, configuration );
  543. replaceOrAddRepositoryConfig( managedRepositoryConfiguration, configuration );
  544. return repo;
  545. }
  546. finally
  547. {
  548. rwLock.writeLock( ).unlock( );
  549. }
  550. }
  551. private void replaceOrAddRepositoryConfig(ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration) {
  552. ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById( managedRepositoryConfiguration.getId() );
  553. if ( oldCfg !=null) {
  554. configuration.removeManagedRepository( oldCfg );
  555. }
  556. configuration.addManagedRepository( managedRepositoryConfiguration );
  557. }
  558. private void replaceOrAddRepositoryConfig(RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration) {
  559. RemoteRepositoryConfiguration oldCfg = configuration.findRemoteRepositoryById( remoteRepositoryConfiguration.getId() );
  560. if ( oldCfg !=null) {
  561. configuration.removeRemoteRepository( oldCfg );
  562. }
  563. configuration.addRemoteRepository( remoteRepositoryConfiguration );
  564. }
  565. public RemoteRepository putRepository( RemoteRepository remoteRepository, Configuration configuration) throws RepositoryException
  566. {
  567. rwLock.writeLock( ).lock( );
  568. try
  569. {
  570. final String id = remoteRepository.getId();
  571. if (managedRepositories.containsKey( id )) {
  572. throw new RepositoryException( "There exists a managed repository with id "+id+". Could not update with remote repository." );
  573. }
  574. RemoteRepository originRepo = remoteRepositories.put( id, remoteRepository );
  575. RemoteRepositoryConfiguration oldCfg=null;
  576. RemoteRepositoryConfiguration newCfg;
  577. try
  578. {
  579. if (originRepo!=null) {
  580. originRepo.close();
  581. }
  582. final RepositoryProvider provider = getProvider( remoteRepository.getType() );
  583. newCfg = provider.getRemoteConfiguration( remoteRepository );
  584. updateRepositoryReferences( provider, remoteRepository, newCfg, configuration );
  585. oldCfg = configuration.findRemoteRepositoryById( id );
  586. if (oldCfg!=null) {
  587. configuration.removeRemoteRepository( oldCfg );
  588. }
  589. configuration.addRemoteRepository( newCfg );
  590. return remoteRepository;
  591. }
  592. catch ( Exception e )
  593. {
  594. // Rollback
  595. if ( originRepo != null )
  596. {
  597. remoteRepositories.put( id, originRepo );
  598. } else {
  599. remoteRepositories.remove( id);
  600. }
  601. if (oldCfg!=null) {
  602. RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById( id );
  603. if (cfg!=null) {
  604. configuration.removeRemoteRepository( cfg );
  605. configuration.addRemoteRepository( oldCfg );
  606. }
  607. }
  608. log.error("Error while adding remote repository {}", e.getMessage(), e);
  609. throw new RepositoryException( "Could not save the configuration" + (e.getMessage( )==null?"":": "+e.getMessage()) );
  610. }
  611. }
  612. finally
  613. {
  614. rwLock.writeLock( ).unlock( );
  615. }
  616. }
  617. /**
  618. * Adds a remote repository, or overwrites the repository definition with the same id, if it exists already.
  619. * The modification is saved to the configuration immediately.
  620. *
  621. * @param remoteRepository the remote repository to add
  622. * @throws RepositoryException if an error occurs during configuration save
  623. */
  624. public RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException
  625. {
  626. rwLock.writeLock( ).lock( );
  627. try
  628. {
  629. Configuration configuration = getArchivaConfiguration().getConfiguration();
  630. try
  631. {
  632. RemoteRepository repo = putRepository( remoteRepository, configuration );
  633. getArchivaConfiguration().save(configuration);
  634. return repo;
  635. }
  636. catch ( RegistryException | IndeterminateConfigurationException e )
  637. {
  638. log.error("Error while saving remote repository {}", e.getMessage(), e);
  639. throw new RepositoryException( "Could not save the configuration" + (e.getMessage( )==null?"":": "+e.getMessage()) );
  640. }
  641. }
  642. finally
  643. {
  644. rwLock.writeLock( ).unlock( );
  645. }
  646. }
  647. /**
  648. * Adds a new repository or updates the repository with the same id, if it exists already.
  649. * The configuration is saved immediately.
  650. *
  651. * @param remoteRepositoryConfiguration the repository configuration
  652. * @return the updated or created repository
  653. * @throws RepositoryException if an error occurs, or the configuration is not valid.
  654. */
  655. public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration) throws RepositoryException
  656. {
  657. rwLock.writeLock( ).lock( );
  658. try
  659. {
  660. final String id = remoteRepositoryConfiguration.getId();
  661. final RepositoryType repositoryType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType() );
  662. Configuration configuration = getArchivaConfiguration().getConfiguration();
  663. RemoteRepository repo = remoteRepositories.get(id);
  664. RemoteRepositoryConfiguration oldCfg = repo!=null ? getProvider( repositoryType ).getRemoteConfiguration( repo ) : null;
  665. repo = putRepository( remoteRepositoryConfiguration, configuration );
  666. try
  667. {
  668. getArchivaConfiguration().save(configuration);
  669. }
  670. catch ( IndeterminateConfigurationException | RegistryException e )
  671. {
  672. if (oldCfg!=null) {
  673. getProvider( repositoryType ).updateRemoteInstance( (EditableRemoteRepository)repo, oldCfg );
  674. }
  675. log.error("Could not save the configuration for repository {}: {}", id, e.getMessage(),e );
  676. throw new RepositoryException( "Could not save the configuration for repository "+id+": "+e.getMessage() );
  677. }
  678. return repo;
  679. }
  680. finally
  681. {
  682. rwLock.writeLock( ).unlock( );
  683. }
  684. }
  685. /**
  686. * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
  687. * the configuration is not saved.
  688. *
  689. * @param remoteRepositoryConfiguration the new or changed repository configuration
  690. * @param configuration the configuration object
  691. * @return the new or updated repository
  692. * @throws RepositoryException if the configuration cannot be saved or updated
  693. */
  694. @SuppressWarnings( "unchecked" )
  695. public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration) throws RepositoryException
  696. {
  697. rwLock.writeLock( ).lock( );
  698. try
  699. {
  700. final String id = remoteRepositoryConfiguration.getId();
  701. final RepositoryType repoType = RepositoryType.valueOf( remoteRepositoryConfiguration.getType() );
  702. RemoteRepository repo;
  703. if (remoteRepositories.containsKey( id )) {
  704. repo = remoteRepositories.get(id);
  705. if (repo instanceof EditableRemoteRepository)
  706. {
  707. getProvider( repoType ).updateRemoteInstance( (EditableRemoteRepository) repo, remoteRepositoryConfiguration );
  708. } else {
  709. throw new RepositoryException( "The repository is not editable "+id );
  710. }
  711. } else
  712. {
  713. repo = getProvider( repoType ).createRemoteInstance( remoteRepositoryConfiguration );
  714. repo.addListener(this);
  715. remoteRepositories.put(id, repo);
  716. }
  717. updateRepositoryReferences( getProvider( repoType ), repo, remoteRepositoryConfiguration, configuration );
  718. replaceOrAddRepositoryConfig( remoteRepositoryConfiguration, configuration );
  719. return repo;
  720. }
  721. finally
  722. {
  723. rwLock.writeLock( ).unlock( );
  724. }
  725. }
  726. public void removeRepository(String repoId) throws RepositoryException {
  727. Repository repo = getRepository(repoId);
  728. if (repo!=null) {
  729. removeRepository(repo);
  730. }
  731. }
  732. @SuppressWarnings( "unchecked" )
  733. public void removeRepository(Repository repo) throws RepositoryException
  734. {
  735. if (repo instanceof RemoteRepository ) {
  736. removeRepository( (RemoteRepository)repo );
  737. } else if (repo instanceof ManagedRepository) {
  738. removeRepository( (ManagedRepository)repo);
  739. } else {
  740. throw new RepositoryException( "Repository type not known: "+repo.getClass() );
  741. }
  742. }
  743. /**
  744. * Removes a managed repository from the registry and configuration, if it exists.
  745. * The change is saved to the configuration immediately.
  746. *
  747. * @param managedRepository the managed repository to remove
  748. * @throws RepositoryException if a error occurs during configuration save
  749. */
  750. public void removeRepository( ManagedRepository managedRepository ) throws RepositoryException
  751. {
  752. final String id = managedRepository.getId();
  753. ManagedRepository repo = getManagedRepository( id );
  754. if (repo!=null) {
  755. rwLock.writeLock().lock();
  756. try {
  757. repo = managedRepositories.remove( id );
  758. if (repo!=null) {
  759. repo.close();
  760. Configuration configuration = getArchivaConfiguration().getConfiguration();
  761. ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById( id );
  762. if (cfg!=null) {
  763. configuration.removeManagedRepository( cfg );
  764. }
  765. getArchivaConfiguration().save( configuration );
  766. }
  767. }
  768. catch ( RegistryException | IndeterminateConfigurationException e )
  769. {
  770. // Rollback
  771. log.error("Could not save config after repository removal: {}", e.getMessage(), e);
  772. managedRepositories.put(repo.getId(), repo);
  773. throw new RepositoryException( "Could not save configuration after repository removal: "+e.getMessage() );
  774. } finally
  775. {
  776. rwLock.writeLock().unlock();
  777. }
  778. }
  779. }
  780. public void removeRepository(ManagedRepository managedRepository, Configuration configuration) throws RepositoryException
  781. {
  782. final String id = managedRepository.getId();
  783. ManagedRepository repo = getManagedRepository( id );
  784. if (repo!=null) {
  785. rwLock.writeLock().lock();
  786. try {
  787. repo = managedRepositories.remove( id );
  788. if (repo!=null) {
  789. repo.close();
  790. ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById( id );
  791. if (cfg!=null) {
  792. configuration.removeManagedRepository( cfg );
  793. }
  794. }
  795. } finally
  796. {
  797. rwLock.writeLock().unlock();
  798. }
  799. }
  800. }
  801. private void doRemoveRepo(RemoteRepository repo, Configuration configuration) {
  802. repo.close();
  803. RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById(repo.getId());
  804. if (cfg != null) {
  805. configuration.removeRemoteRepository(cfg);
  806. }
  807. List<ProxyConnectorConfiguration> proxyConnectors = new ArrayList<>(configuration.getProxyConnectors());
  808. for (ProxyConnectorConfiguration proxyConnector : proxyConnectors) {
  809. if (StringUtils.equals(proxyConnector.getTargetRepoId(), repo.getId())) {
  810. configuration.removeProxyConnector(proxyConnector);
  811. }
  812. }
  813. }
  814. /**
  815. * Removes the remote repository from the registry and configuration.
  816. * The change is saved to the configuration immediately.
  817. *
  818. * @param remoteRepository the remote repository to remove
  819. * @throws RepositoryException if a error occurs during configuration save
  820. */
  821. public void removeRepository( RemoteRepository remoteRepository ) throws RepositoryException
  822. {
  823. final String id = remoteRepository.getId();
  824. RemoteRepository repo = getRemoteRepository( id );
  825. if (repo!=null) {
  826. rwLock.writeLock().lock();
  827. try {
  828. repo = remoteRepositories.remove( id );
  829. if (repo!=null) {
  830. Configuration configuration = getArchivaConfiguration().getConfiguration();
  831. doRemoveRepo(repo, configuration);
  832. getArchivaConfiguration().save( configuration );
  833. }
  834. }
  835. catch ( RegistryException | IndeterminateConfigurationException e )
  836. {
  837. // Rollback
  838. log.error("Could not save config after repository removal: {}", e.getMessage(), e);
  839. remoteRepositories.put(repo.getId(), repo);
  840. throw new RepositoryException( "Could not save configuration after repository removal: "+e.getMessage() );
  841. } finally
  842. {
  843. rwLock.writeLock().unlock();
  844. }
  845. }
  846. }
  847. public void removeRepository( RemoteRepository remoteRepository, Configuration configuration) throws RepositoryException
  848. {
  849. final String id = remoteRepository.getId();
  850. RemoteRepository repo = getRemoteRepository( id );
  851. if (repo!=null) {
  852. rwLock.writeLock().lock();
  853. try {
  854. repo = remoteRepositories.remove( id );
  855. if (repo!=null) {
  856. doRemoveRepo(repo, configuration);
  857. }
  858. } finally
  859. {
  860. rwLock.writeLock().unlock();
  861. }
  862. }
  863. }
  864. /**
  865. * Reloads the registry from the configuration.
  866. */
  867. public void reload() {
  868. initialize();
  869. }
  870. /**
  871. * Resets the indexing context of a given repository.
  872. *
  873. * @param repo
  874. * @throws IndexUpdateFailedException
  875. */
  876. @SuppressWarnings( "unchecked" )
  877. public void resetIndexingContext(Repository repo) throws IndexUpdateFailedException {
  878. if (repo.hasIndex() && repo instanceof EditableRepository) {
  879. EditableRepository eRepo = (EditableRepository) repo;
  880. ArchivaIndexingContext newCtx = getIndexManager(repo.getType()).reset(repo.getIndexingContext());
  881. eRepo.setIndexingContext(newCtx);
  882. }
  883. }
  884. /**
  885. * Creates a new repository instance with the same settings as this one. The cloned repository is not
  886. * registered or saved to the configuration.
  887. *
  888. * @param repo The origin repository
  889. * @return The cloned repository.
  890. */
  891. public ManagedRepository clone(ManagedRepository repo, String newId) throws RepositoryException
  892. {
  893. if (managedRepositories.containsKey(newId) || remoteRepositories.containsKey(newId)) {
  894. throw new RepositoryException("The given id exists already "+newId);
  895. }
  896. RepositoryProvider provider = getProvider(repo.getType());
  897. ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration(repo);
  898. cfg.setId(newId);
  899. ManagedRepository cloned = provider.createManagedInstance(cfg);
  900. cloned.addListener(this);
  901. return cloned;
  902. }
  903. @SuppressWarnings( "unchecked" )
  904. public <T extends Repository> Repository clone(T repo, String newId) throws RepositoryException {
  905. if (repo instanceof RemoteRepository ) {
  906. return this.clone((RemoteRepository)repo, newId);
  907. } else if (repo instanceof ManagedRepository) {
  908. return this.clone((ManagedRepository)repo, newId);
  909. } else {
  910. throw new RepositoryException("This repository class is not supported "+ repo.getClass().getName());
  911. }
  912. }
  913. /**
  914. * Creates a new repository instance with the same settings as this one. The cloned repository is not
  915. * registered or saved to the configuration.
  916. *
  917. * @param repo The origin repository
  918. * @return The cloned repository.
  919. */
  920. public RemoteRepository clone( RemoteRepository repo, String newId) throws RepositoryException
  921. {
  922. if (managedRepositories.containsKey(newId) || remoteRepositories.containsKey(newId)) {
  923. throw new RepositoryException("The given id exists already "+newId);
  924. }
  925. RepositoryProvider provider = getProvider(repo.getType());
  926. RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration(repo);
  927. cfg.setId(newId);
  928. RemoteRepository cloned = provider.createRemoteInstance(cfg);
  929. cloned.addListener(this);
  930. return cloned;
  931. }
  932. @Override
  933. public void configurationEvent(ConfigurationEvent event) {
  934. }
  935. @Override
  936. public void addListener(RepositoryEventListener listener) {
  937. if (!this.listeners.contains(listener)) {
  938. this.listeners.add(listener);
  939. }
  940. }
  941. @Override
  942. public void removeListener(RepositoryEventListener listener) {
  943. this.listeners.remove(listener);
  944. }
  945. @Override
  946. public void clearListeners() {
  947. this.listeners.clear();
  948. }
  949. @SuppressWarnings( "unchecked" )
  950. @Override
  951. public <T> void raise(RepositoryEvent<T> event) {
  952. if (event instanceof IndexCreationEvent ) {
  953. if (managedRepositories.containsKey(event.getRepository().getId()) ||
  954. remoteRepositories.containsKey(event.getRepository().getId())) {
  955. EditableRepository repo = (EditableRepository) event.getRepository();
  956. if (repo != null && repo.getIndexingContext()!=null) {
  957. try {
  958. ArchivaIndexManager idxmgr = getIndexManager(repo.getType());
  959. if (idxmgr != null) {
  960. ArchivaIndexingContext newCtx = idxmgr.move(repo.getIndexingContext(), repo);
  961. repo.setIndexingContext(newCtx);
  962. idxmgr.updateLocalIndexPath(repo);
  963. }
  964. } catch (IndexCreationFailedException e) {
  965. log.error("Could not move index to new directory {}", e.getMessage(), e);
  966. }
  967. }
  968. }
  969. }
  970. for(RepositoryEventListener listener : listeners) {
  971. listener.raise(event);
  972. }
  973. }
  974. }