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 40KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193
  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.AbstractRepositoryConfiguration;
  22. import org.apache.archiva.configuration.ArchivaConfiguration;
  23. import org.apache.archiva.configuration.Configuration;
  24. import org.apache.archiva.configuration.ConfigurationEvent;
  25. import org.apache.archiva.configuration.ConfigurationListener;
  26. import org.apache.archiva.configuration.IndeterminateConfigurationException;
  27. import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
  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.EditableRepository;
  40. import org.apache.archiva.repository.ManagedRepository;
  41. import org.apache.archiva.repository.RemoteRepository;
  42. import org.apache.archiva.repository.Repository;
  43. import org.apache.archiva.repository.RepositoryException;
  44. import org.apache.archiva.repository.RepositoryGroup;
  45. import org.apache.archiva.repository.RepositoryHandler;
  46. import org.apache.archiva.repository.RepositoryProvider;
  47. import org.apache.archiva.repository.RepositoryRegistry;
  48. import org.apache.archiva.repository.RepositoryType;
  49. import org.apache.archiva.repository.UnsupportedRepositoryTypeException;
  50. import org.apache.archiva.repository.event.RepositoryIndexEvent;
  51. import org.apache.archiva.repository.event.RepositoryRegistryEvent;
  52. import org.apache.archiva.repository.metadata.MetadataReader;
  53. import org.apache.archiva.repository.storage.StorageAsset;
  54. import org.apache.archiva.repository.validation.CheckedResult;
  55. import org.apache.archiva.repository.validation.RepositoryValidator;
  56. import org.apache.archiva.repository.validation.ValidationError;
  57. import org.apache.archiva.repository.validation.ValidationResponse;
  58. import org.apache.commons.collections4.ListUtils;
  59. import org.slf4j.Logger;
  60. import org.slf4j.LoggerFactory;
  61. import org.springframework.stereotype.Service;
  62. import javax.annotation.PostConstruct;
  63. import javax.annotation.PreDestroy;
  64. import javax.inject.Inject;
  65. import java.util.Collection;
  66. import java.util.Collections;
  67. import java.util.HashMap;
  68. import java.util.List;
  69. import java.util.Map;
  70. import java.util.Set;
  71. import java.util.TreeSet;
  72. import java.util.concurrent.atomic.AtomicBoolean;
  73. import java.util.concurrent.locks.ReentrantReadWriteLock;
  74. import java.util.stream.Collectors;
  75. import java.util.stream.Stream;
  76. /**
  77. * Registry for repositories. This is the central entry point for repositories. It provides methods for
  78. * retrieving, adding and removing repositories.
  79. * <p>
  80. * The modification methods addXX and removeXX persist the changes immediately to the configuration. If the
  81. * configuration save fails the changes are rolled back.
  82. * <p>
  83. * TODO: Audit events
  84. *
  85. * @since 3.0
  86. */
  87. @Service( "repositoryRegistry" )
  88. public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHandler<Event>,
  89. RepositoryRegistry
  90. {
  91. private static final Logger log = LoggerFactory.getLogger( RepositoryRegistry.class );
  92. /**
  93. * We inject all repository providers
  94. */
  95. @Inject
  96. List<RepositoryProvider> repositoryProviders;
  97. @SuppressWarnings( "SpringJavaInjectionPointsAutowiringInspection" )
  98. @Inject
  99. IndexManagerFactory indexManagerFactory;
  100. @Inject
  101. List<MetadataReader> metadataReaderList;
  102. @Inject
  103. List<RepositoryValidator<? extends Repository>> repositoryValidatorList;
  104. private boolean ignoreIndexing = false;
  105. private final EventManager eventManager;
  106. private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock( );
  107. private RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration> groupHandler;
  108. private RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration> managedRepositoryHandler;
  109. private RepositoryHandler<RemoteRepository, RemoteRepositoryConfiguration> remoteRepositoryHandler;
  110. private final Set<RepositoryValidator<? extends Repository>> validators;
  111. private final ConfigurationHandler configurationHandler;
  112. private final AtomicBoolean groups_initalized = new AtomicBoolean( false );
  113. private final AtomicBoolean managed_initialized = new AtomicBoolean( false );
  114. private final AtomicBoolean remote_initialized = new AtomicBoolean( false );
  115. public ArchivaRepositoryRegistry( ConfigurationHandler configurationHandler, List<RepositoryValidator<? extends Repository>> validatorList )
  116. {
  117. this.eventManager = new EventManager( this );
  118. this.configurationHandler = configurationHandler;
  119. this.validators = initValidatorList( validatorList );
  120. }
  121. private Set<RepositoryValidator<? extends Repository>> initValidatorList( List<RepositoryValidator<? extends Repository>> validators )
  122. {
  123. TreeSet<RepositoryValidator<? extends Repository>> val = new TreeSet<>( );
  124. for ( RepositoryValidator<? extends Repository> validator : validators )
  125. {
  126. val.add( validator );
  127. validator.setRepositoryRegistry( this );
  128. }
  129. return val;
  130. }
  131. @Override
  132. public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration )
  133. {
  134. this.configurationHandler.setArchivaConfiguration( archivaConfiguration );
  135. }
  136. @PostConstruct
  137. private void initialize( )
  138. {
  139. rwLock.writeLock( ).lock( );
  140. try
  141. {
  142. log.debug( "Initializing repository registry" );
  143. initializeManagedRepositories();
  144. initializeRemoteRepositories();
  145. initializeRepositoryGroups( );
  146. for ( RepositoryProvider provider : repositoryProviders )
  147. {
  148. provider.addRepositoryEventHandler( this );
  149. }
  150. this.configurationHandler.addListener( this );
  151. }
  152. finally
  153. {
  154. rwLock.writeLock( ).unlock( );
  155. }
  156. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.RELOADED, this ) );
  157. if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
  158. {
  159. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
  160. }
  161. }
  162. private void initializeRepositoryGroups( )
  163. {
  164. if ( this.groupHandler != null )
  165. {
  166. this.groupHandler.initializeFromConfig( );
  167. this.groups_initalized.set( true );
  168. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.GROUPS_INITIALIZED, this ) );
  169. }
  170. }
  171. private void initializeManagedRepositories( )
  172. {
  173. if ( this.managedRepositoryHandler != null )
  174. {
  175. this.managedRepositoryHandler.initializeFromConfig( );
  176. this.managed_initialized.set( true );
  177. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.MANAGED_REPOS_INITIALIZED, this ) );
  178. }
  179. }
  180. private void initializeRemoteRepositories() {
  181. if (this.remoteRepositoryHandler != null ){
  182. this.remoteRepositoryHandler.initializeFromConfig( );
  183. this.remote_initialized.set( true );
  184. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.REMOTE_REPOS_INITIALIZED, this ) );
  185. }
  186. }
  187. public void registerGroupHandler( RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration> groupHandler )
  188. {
  189. this.groupHandler = groupHandler;
  190. doRegister( groupHandler );
  191. initializeRepositoryGroups( );
  192. if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
  193. {
  194. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
  195. }
  196. }
  197. public void registerManagedRepositoryHandler( RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration> managedRepositoryHandler )
  198. {
  199. this.managedRepositoryHandler = managedRepositoryHandler;
  200. doRegister( managedRepositoryHandler );
  201. initializeManagedRepositories();
  202. if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
  203. {
  204. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
  205. }
  206. }
  207. public void registerRemoteRepositoryHandler( RepositoryHandler<RemoteRepository, RemoteRepositoryConfiguration> remoteRepositoryHandler )
  208. {
  209. this.remoteRepositoryHandler = remoteRepositoryHandler;
  210. doRegister( remoteRepositoryHandler );
  211. initializeRemoteRepositories();
  212. if ( managed_initialized.get( ) && remote_initialized.get( ) && groups_initalized.get( ) )
  213. {
  214. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.INITIALIZED, this ) );
  215. }
  216. }
  217. @PreDestroy
  218. public void destroy( )
  219. {
  220. managedRepositoryHandler.close( );
  221. remoteRepositoryHandler.close();
  222. groupHandler.close( );
  223. pushEvent( new RepositoryRegistryEvent( RepositoryRegistryEvent.DESTROYED, this ) );
  224. }
  225. public Map<RepositoryType, RepositoryProvider> getRepositoryProviderMap( )
  226. {
  227. Map<RepositoryType, RepositoryProvider> map = new HashMap<>( );
  228. if ( repositoryProviders != null )
  229. {
  230. for ( RepositoryProvider provider : repositoryProviders )
  231. {
  232. for ( RepositoryType type : provider.provides( ) )
  233. {
  234. map.put( type, provider );
  235. }
  236. }
  237. }
  238. return map;
  239. }
  240. public RepositoryProvider getProvider( RepositoryType type ) throws RepositoryException
  241. {
  242. return repositoryProviders.stream( ).filter( repositoryProvider -> repositoryProvider.provides( ).contains( type ) ).findFirst( ).orElseThrow( ( ) -> new RepositoryException( "Repository type cannot be handled: " + type ) );
  243. }
  244. @Override
  245. public ArchivaIndexManager getIndexManager( RepositoryType type )
  246. {
  247. return indexManagerFactory.getIndexManager( type );
  248. }
  249. @Override
  250. public MetadataReader getMetadataReader( final RepositoryType type ) throws UnsupportedRepositoryTypeException
  251. {
  252. if ( metadataReaderList != null )
  253. {
  254. return metadataReaderList.stream( ).filter( mr -> mr.isValidForType( type ) ).findFirst( ).orElseThrow( ( ) -> new UnsupportedRepositoryTypeException( type ) );
  255. }
  256. else
  257. {
  258. throw new UnsupportedRepositoryTypeException( type );
  259. }
  260. }
  261. /**
  262. * Returns all repositories that are registered. There is no defined order of the returned repositories.
  263. *
  264. * @return a list of managed and remote repositories
  265. */
  266. @Override
  267. public Collection<Repository> getRepositories( )
  268. {
  269. rwLock.readLock( ).lock( );
  270. try
  271. {
  272. return Stream.concat( managedRepositoryHandler.getAll().stream( ), remoteRepositoryHandler.getAll().stream( ) ).collect( Collectors.toList( ) );
  273. }
  274. finally
  275. {
  276. rwLock.readLock( ).unlock( );
  277. }
  278. }
  279. /**
  280. * Returns only the managed repositories. There is no defined order of the returned repositories.
  281. *
  282. * @return a list of managed repositories
  283. */
  284. @Override
  285. public Collection<ManagedRepository> getManagedRepositories( )
  286. {
  287. rwLock.readLock( ).lock( );
  288. try
  289. {
  290. return managed_initialized.get() ? managedRepositoryHandler.getAll( ) : Collections.emptyList();
  291. }
  292. finally
  293. {
  294. rwLock.readLock( ).unlock( );
  295. }
  296. }
  297. /**
  298. * Returns only the remote repositories. There is no defined order of the returned repositories.
  299. *
  300. * @return a list of remote repositories
  301. */
  302. @Override
  303. public Collection<RemoteRepository> getRemoteRepositories( )
  304. {
  305. rwLock.readLock( ).lock( );
  306. try
  307. {
  308. return remote_initialized.get() ? remoteRepositoryHandler.getAll( ) : Collections.emptyList();
  309. }
  310. finally
  311. {
  312. rwLock.readLock( ).unlock( );
  313. }
  314. }
  315. @Override
  316. public Collection<RepositoryGroup> getRepositoryGroups( )
  317. {
  318. rwLock.readLock( ).lock( );
  319. try
  320. {
  321. return groupHandler.getAll( );
  322. }
  323. finally
  324. {
  325. rwLock.readLock( ).unlock( );
  326. }
  327. }
  328. /**
  329. * Returns the repository with the given id. The returned repository may be a managed or remote repository.
  330. * It returns null, if no repository is registered with the given id.
  331. *
  332. * @param repoId the repository id
  333. * @return the repository if found, otherwise null
  334. */
  335. @Override
  336. public Repository getRepository( String repoId )
  337. {
  338. rwLock.readLock( ).lock( );
  339. try
  340. {
  341. log.debug( "getRepository {}", repoId );
  342. if ( managedRepositoryHandler.hasRepository( repoId ) )
  343. {
  344. log.debug( "Managed repo" );
  345. return managedRepositoryHandler.get( repoId );
  346. }
  347. else if ( remoteRepositoryHandler.hasRepository( repoId ) )
  348. {
  349. log.debug( "Remote repo" );
  350. return remoteRepositoryHandler.get( repoId );
  351. }
  352. else if ( groupHandler.hasRepository( repoId ) )
  353. {
  354. return groupHandler.get( repoId );
  355. }
  356. else
  357. {
  358. return null;
  359. }
  360. }
  361. finally
  362. {
  363. rwLock.readLock( ).unlock( );
  364. }
  365. }
  366. /**
  367. * Convenience method, that returns the managed repository with the given id.
  368. * It returns null, if no managed repository is registered with this id.
  369. *
  370. * @param repoId the repository id
  371. * @return the managed repository if found, otherwise null
  372. */
  373. @Override
  374. public ManagedRepository getManagedRepository( String repoId )
  375. {
  376. rwLock.readLock( ).lock( );
  377. try
  378. {
  379. return managed_initialized.get() ? managedRepositoryHandler.get( repoId ) : null;
  380. }
  381. finally
  382. {
  383. rwLock.readLock( ).unlock( );
  384. }
  385. }
  386. /**
  387. * Convenience method, that returns the remote repository with the given id.
  388. * It returns null, if no remote repository is registered with this id.
  389. *
  390. * @param repoId the repository id
  391. * @return the remote repository if found, otherwise null
  392. */
  393. @Override
  394. public RemoteRepository getRemoteRepository( String repoId )
  395. {
  396. rwLock.readLock( ).lock( );
  397. try
  398. {
  399. return remote_initialized.get() ? remoteRepositoryHandler.get( repoId ) : null;
  400. }
  401. finally
  402. {
  403. rwLock.readLock( ).unlock( );
  404. }
  405. }
  406. @Override
  407. public RepositoryGroup getRepositoryGroup( String groupId )
  408. {
  409. rwLock.readLock( ).lock( );
  410. try
  411. {
  412. return groupHandler.get( groupId );
  413. }
  414. finally
  415. {
  416. rwLock.readLock( ).unlock( );
  417. }
  418. }
  419. @Override
  420. public boolean hasRepository( String repoId )
  421. {
  422. return ( managedRepositoryHandler != null && managedRepositoryHandler.hasRepository( repoId ) )
  423. || ( remoteRepositoryHandler != null && remoteRepositoryHandler.hasRepository( repoId ) )
  424. || ( this.groupHandler != null && groupHandler.hasRepository( repoId ) );
  425. }
  426. @Override
  427. public boolean hasManagedRepository( String repoId )
  428. {
  429. return managedRepositoryHandler!=null && managedRepositoryHandler.hasRepository( repoId );
  430. }
  431. @Override
  432. public boolean hasRemoteRepository( String repoId )
  433. {
  434. return remoteRepositoryHandler!=null && remoteRepositoryHandler.hasRepository( repoId );
  435. }
  436. @Override
  437. public boolean hasRepositoryGroup( String groupId )
  438. {
  439. return this.groupHandler != null && groupHandler.hasRepository( groupId );
  440. }
  441. protected void saveConfiguration( Configuration configuration ) throws IndeterminateConfigurationException, RegistryException
  442. {
  443. configurationHandler.save( configuration, ConfigurationHandler.REGISTRY_EVENT_TAG );
  444. }
  445. /**
  446. * Adds a new repository to the current list, or replaces the repository definition with
  447. * the same id, if it exists already.
  448. * The change is saved to the configuration immediately.
  449. *
  450. * @param managedRepository the new repository.
  451. * @throws RepositoryException if the new repository could not be saved to the configuration.
  452. */
  453. @Override
  454. public ManagedRepository putRepository( ManagedRepository managedRepository ) throws RepositoryException
  455. {
  456. rwLock.writeLock( ).lock( );
  457. try
  458. {
  459. return managed_initialized.get() ? managedRepositoryHandler.put( managedRepository ) : null;
  460. }
  461. finally
  462. {
  463. rwLock.writeLock( ).unlock( );
  464. }
  465. }
  466. /**
  467. * Adds a new repository or updates the repository with the same id, if it exists already.
  468. * The configuration is saved immediately.
  469. *
  470. * @param managedRepositoryConfiguration the repository configuration
  471. * @return the updated or created repository
  472. * @throws RepositoryException if an error occurs, or the configuration is not valid.
  473. */
  474. @Override
  475. public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration ) throws RepositoryException
  476. {
  477. rwLock.writeLock( ).lock( );
  478. try
  479. {
  480. return managedRepositoryHandler.put( managedRepositoryConfiguration );
  481. }
  482. finally
  483. {
  484. rwLock.writeLock( ).unlock( );
  485. }
  486. }
  487. /**
  488. * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
  489. * the configuration is not saved.
  490. *
  491. * @param managedRepositoryConfiguration the new or changed managed repository configuration
  492. * @param configuration the configuration object (may be <code>null</code>)
  493. * @return the new or updated repository
  494. * @throws RepositoryException if the configuration cannot be saved or updated
  495. */
  496. @Override
  497. public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration ) throws RepositoryException
  498. {
  499. rwLock.writeLock( ).lock( );
  500. try
  501. {
  502. return managedRepositoryHandler.put( managedRepositoryConfiguration, configuration );
  503. }
  504. finally
  505. {
  506. rwLock.writeLock( ).unlock( );
  507. }
  508. }
  509. /**
  510. * Adds a new repository group to the current list, or replaces the repository group definition with
  511. * the same id, if it exists already.
  512. * The change is saved to the configuration immediately.
  513. *
  514. * @param repositoryGroup the new repository group.
  515. * @throws RepositoryException if the new repository group could not be saved to the configuration.
  516. */
  517. @Override
  518. public RepositoryGroup putRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
  519. {
  520. rwLock.writeLock( ).lock( );
  521. try
  522. {
  523. if ( this.groupHandler == null )
  524. {
  525. throw new RepositoryException( "Fatal error. RepositoryGroupHandler not registered!" );
  526. }
  527. return this.groupHandler.put( repositoryGroup );
  528. }
  529. finally
  530. {
  531. rwLock.writeLock( ).unlock( );
  532. }
  533. }
  534. /**
  535. * Adds a new repository group or updates the repository with the same id, if it exists already.
  536. * The configuration is saved immediately.
  537. *
  538. * @param repositoryGroupConfiguration the repository configuration
  539. * @return the updated or created repository
  540. * @throws RepositoryException if an error occurs, or the configuration is not valid.
  541. */
  542. @Override
  543. public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException
  544. {
  545. rwLock.writeLock( ).lock( );
  546. try
  547. {
  548. return groupHandler.put( repositoryGroupConfiguration );
  549. }
  550. finally
  551. {
  552. rwLock.writeLock( ).unlock( );
  553. }
  554. }
  555. @Override
  556. public CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> putRepositoryGroupAndValidate( RepositoryGroupConfiguration repositoryGroupConfiguration )
  557. throws RepositoryException
  558. {
  559. rwLock.writeLock( ).lock( );
  560. try
  561. {
  562. return groupHandler.putWithCheck( repositoryGroupConfiguration, groupHandler.getValidator( ) );
  563. }
  564. finally
  565. {
  566. rwLock.writeLock( ).unlock( );
  567. }
  568. }
  569. /**
  570. * Adds a new repository group or updates the repository group with the same id. The given configuration object is updated, but
  571. * the configuration is not saved.
  572. *
  573. * @param repositoryGroupConfiguration The configuration of the new or changed repository group.
  574. * @param configuration The configuration object. If it is <code>null</code>, the configuration is not saved.
  575. * @return The new or updated repository group
  576. * @throws RepositoryException if the configuration cannot be saved or updated
  577. */
  578. @Override
  579. public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException
  580. {
  581. rwLock.writeLock( ).lock( );
  582. try
  583. {
  584. return groupHandler.put( repositoryGroupConfiguration, configuration );
  585. }
  586. finally
  587. {
  588. rwLock.writeLock( ).unlock( );
  589. }
  590. }
  591. /**
  592. * Adds a remote repository, or overwrites the repository definition with the same id, if it exists already.
  593. * The modification is saved to the configuration immediately.
  594. *
  595. * @param remoteRepository the remote repository to add
  596. * @throws RepositoryException if an error occurs during configuration save
  597. */
  598. @Override
  599. public RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException
  600. {
  601. rwLock.writeLock( ).lock( );
  602. try
  603. {
  604. return remoteRepositoryHandler.put( remoteRepository );
  605. }
  606. finally
  607. {
  608. rwLock.writeLock( ).unlock( );
  609. }
  610. }
  611. /**
  612. * Adds a new repository or updates the repository with the same id, if it exists already.
  613. * The configuration is saved immediately.
  614. *
  615. * @param remoteRepositoryConfiguration the repository configuration
  616. * @return the updated or created repository
  617. * @throws RepositoryException if an error occurs, or the configuration is not valid.
  618. */
  619. @Override
  620. public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration ) throws RepositoryException
  621. {
  622. rwLock.writeLock( ).lock( );
  623. try
  624. {
  625. return remoteRepositoryHandler.put( remoteRepositoryConfiguration );
  626. }
  627. finally
  628. {
  629. rwLock.writeLock( ).unlock( );
  630. }
  631. }
  632. /**
  633. * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but
  634. * the configuration is not saved.
  635. *
  636. * @param remoteRepositoryConfiguration the new or changed repository configuration
  637. * @param configuration the configuration object
  638. * @return the new or updated repository
  639. * @throws RepositoryException if the configuration cannot be saved or updated
  640. */
  641. @Override
  642. public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration ) throws RepositoryException
  643. {
  644. rwLock.writeLock( ).lock( );
  645. try
  646. {
  647. return remoteRepositoryHandler.put( remoteRepositoryConfiguration, configuration );
  648. }
  649. finally
  650. {
  651. rwLock.writeLock( ).unlock( );
  652. }
  653. }
  654. @Override
  655. public void removeRepository( String repoId ) throws RepositoryException
  656. {
  657. Repository repo = getRepository( repoId );
  658. if ( repo != null )
  659. {
  660. removeRepository( repo );
  661. }
  662. }
  663. @Override
  664. public void removeRepository( Repository repo ) throws RepositoryException
  665. {
  666. if ( repo == null )
  667. {
  668. log.warn( "Trying to remove null repository" );
  669. return;
  670. }
  671. if ( repo instanceof RemoteRepository )
  672. {
  673. removeRepository( (RemoteRepository) repo );
  674. }
  675. else if ( repo instanceof ManagedRepository )
  676. {
  677. removeRepository( (ManagedRepository) repo );
  678. }
  679. else if ( repo instanceof RepositoryGroup )
  680. {
  681. removeRepositoryGroup( (RepositoryGroup) repo );
  682. }
  683. else
  684. {
  685. throw new RepositoryException( "Repository type not known: " + repo.getClass( ) );
  686. }
  687. }
  688. /**
  689. * Removes a managed repository from the registry and configuration, if it exists.
  690. * The change is saved to the configuration immediately.
  691. *
  692. * @param managedRepository the managed repository to remove
  693. * @throws RepositoryException if a error occurs during configuration save
  694. */
  695. @Override
  696. public void removeRepository( ManagedRepository managedRepository ) throws RepositoryException
  697. {
  698. if ( managedRepository == null )
  699. {
  700. return;
  701. }
  702. rwLock.writeLock( ).lock( );
  703. try
  704. {
  705. if (managed_initialized.get() ) managedRepositoryHandler.remove( managedRepository.getId( ) );
  706. }
  707. finally
  708. {
  709. rwLock.writeLock( ).unlock( );
  710. }
  711. }
  712. @Override
  713. public void removeRepository( ManagedRepository managedRepository, Configuration configuration ) throws RepositoryException
  714. {
  715. if ( managedRepository == null )
  716. {
  717. return;
  718. }
  719. rwLock.writeLock( ).lock( );
  720. try
  721. {
  722. if (managed_initialized.get()) managedRepositoryHandler.remove( managedRepository.getId( ), configuration );
  723. }
  724. finally
  725. {
  726. rwLock.writeLock( ).unlock( );
  727. }
  728. }
  729. /**
  730. * Removes a repository group from the registry and configuration, if it exists.
  731. * The change is saved to the configuration immediately.
  732. *
  733. * @param repositoryGroup the repository group to remove
  734. * @throws RepositoryException if a error occurs during configuration save
  735. */
  736. @Override
  737. public void removeRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException
  738. {
  739. if ( repositoryGroup == null )
  740. {
  741. return;
  742. }
  743. final String id = repositoryGroup.getId( );
  744. if ( groupHandler.hasRepository( id ) )
  745. {
  746. rwLock.writeLock( ).lock( );
  747. try
  748. {
  749. groupHandler.remove( id );
  750. }
  751. finally
  752. {
  753. rwLock.writeLock( ).unlock( );
  754. }
  755. }
  756. }
  757. @Override
  758. public void removeRepositoryGroup( RepositoryGroup repositoryGroup, Configuration configuration ) throws RepositoryException
  759. {
  760. if ( repositoryGroup == null )
  761. {
  762. return;
  763. }
  764. final String id = repositoryGroup.getId( );
  765. if ( groupHandler.hasRepository( id ) )
  766. {
  767. rwLock.writeLock( ).lock( );
  768. try
  769. {
  770. groupHandler.remove( id, configuration );
  771. }
  772. finally
  773. {
  774. rwLock.writeLock( ).unlock( );
  775. }
  776. }
  777. }
  778. /**
  779. * Removes the remote repository from the registry and configuration.
  780. * The change is saved to the configuration immediately.
  781. *
  782. * @param remoteRepository the remote repository to remove
  783. * @throws RepositoryException if a error occurs during configuration save
  784. */
  785. @Override
  786. public void removeRepository( RemoteRepository remoteRepository ) throws RepositoryException
  787. {
  788. if ( remoteRepository == null )
  789. {
  790. return;
  791. }
  792. final String id = remoteRepository.getId( );
  793. if ( remoteRepositoryHandler.hasRepository( id ) )
  794. {
  795. rwLock.writeLock( ).lock( );
  796. try
  797. {
  798. remoteRepositoryHandler.remove( id );
  799. }
  800. finally
  801. {
  802. rwLock.writeLock( ).unlock( );
  803. }
  804. }
  805. }
  806. @Override
  807. public void removeRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException
  808. {
  809. if ( remoteRepository == null )
  810. {
  811. return;
  812. }
  813. final String id = remoteRepository.getId( );
  814. if ( remoteRepositoryHandler.hasRepository( id ) )
  815. {
  816. rwLock.writeLock( ).lock( );
  817. try
  818. {
  819. remoteRepositoryHandler.remove( id, configuration );
  820. }
  821. finally
  822. {
  823. rwLock.writeLock( ).unlock( );
  824. }
  825. }
  826. }
  827. /**
  828. * Reloads the registry from the configuration.
  829. */
  830. @Override
  831. public void reload( )
  832. {
  833. initialize( );
  834. }
  835. /**
  836. * Resets the indexing context of a given repository.
  837. *
  838. * @param repository The repository
  839. * @throws IndexUpdateFailedException If the index could not be resetted.
  840. */
  841. @Override
  842. public void resetIndexingContext( Repository repository ) throws IndexUpdateFailedException
  843. {
  844. if ( repository.hasIndex( ) && repository instanceof EditableRepository )
  845. {
  846. EditableRepository eRepo = (EditableRepository) repository;
  847. ArchivaIndexingContext newCtx = getIndexManager( repository.getType( ) ).reset( repository.getIndexingContext( ) );
  848. eRepo.setIndexingContext( newCtx );
  849. }
  850. }
  851. /**
  852. * Creates a new repository instance with the same settings as this one. The cloned repository is not
  853. * registered or saved to the configuration.
  854. *
  855. * @param repo The origin repository
  856. * @return The cloned repository.
  857. */
  858. public ManagedRepository clone( ManagedRepository repo, String newId ) throws RepositoryException
  859. {
  860. if (isRegisteredId( newId )) {
  861. throw new RepositoryException( "The new id exists already: " + newId );
  862. }
  863. return managedRepositoryHandler.clone( repo, newId );
  864. }
  865. /**
  866. * Creates a new repository instance with the same settings as this one. The cloned repository is not
  867. * registered or saved to the configuration.
  868. *
  869. * @param repo The origin repository
  870. * @return The cloned repository.
  871. */
  872. public RemoteRepository clone( RemoteRepository repo, String newId ) throws RepositoryException
  873. {
  874. if (isRegisteredId( newId )) {
  875. throw new RepositoryException( "The new id exists already: " + newId );
  876. }
  877. return remoteRepositoryHandler.clone( repo, newId );
  878. }
  879. @SuppressWarnings( "unchecked" )
  880. @Override
  881. public <T extends Repository> T clone( T repo, String newId ) throws RepositoryException
  882. {
  883. if (isRegisteredId( newId )) {
  884. throw new RepositoryException( "The new id exists already: " + newId );
  885. }
  886. if ( repo instanceof RemoteRepository )
  887. {
  888. return (T) remoteRepositoryHandler.clone( (RemoteRepository) repo, newId );
  889. }
  890. else if ( repo instanceof ManagedRepository )
  891. {
  892. return (T) managedRepositoryHandler.clone( (ManagedRepository) repo, newId );
  893. }
  894. else if (repo instanceof RepositoryGroup) {
  895. return (T) groupHandler.clone( (RepositoryGroup) repo, newId );
  896. }
  897. else
  898. {
  899. throw new RepositoryException( "This repository class is not supported " + repo.getClass( ).getName( ) );
  900. }
  901. }
  902. @Override
  903. public Repository getRepositoryOfAsset( StorageAsset asset )
  904. {
  905. if ( asset instanceof Repository )
  906. {
  907. return (Repository) asset;
  908. }
  909. else
  910. {
  911. return getRepositories( ).stream( ).filter( r -> r.getRoot( )
  912. .getStorage( ).equals( asset.getStorage( ) ) ).findFirst( ).orElse( null );
  913. }
  914. }
  915. @Override
  916. public <R extends Repository> ValidationResponse<R> validateRepository( R repository )
  917. {
  918. @SuppressWarnings( "unchecked" ) Map<String, List<ValidationError>> errorMap = this.validators.stream( )
  919. .filter( ( validator ) -> validator.getType( ).equals( RepositoryType.ALL ) || repository.getType( ).equals( validator.getType( ) ) )
  920. .filter( val -> val.isFlavour( repository.getClass( ) ) )
  921. .flatMap( validator -> ( (RepositoryValidator<R>) validator ).apply( repository ).getResult( ).entrySet( ).stream( ) )
  922. .collect( Collectors.toMap(
  923. Map.Entry::getKey,
  924. Map.Entry::getValue,
  925. ListUtils::union
  926. ) );
  927. return new ValidationResponse<>( repository, errorMap );
  928. }
  929. @Override
  930. public <R extends Repository> ValidationResponse<R> validateRepositoryForUpdate( R repository )
  931. {
  932. @SuppressWarnings( "unchecked" ) Map<String, List<ValidationError>> errorMap = this.validators.stream( )
  933. .filter( ( validator ) -> validator.getType( ).equals( RepositoryType.ALL ) || repository.getType( ).equals( validator.getType( ) ) )
  934. .filter( val -> val.isFlavour( repository.getClass( ) ) )
  935. .flatMap( validator -> ( (RepositoryValidator<R>) validator ).applyForUpdate( repository ).getResult( ).entrySet( ).stream( ) )
  936. .collect( Collectors.toMap(
  937. Map.Entry::getKey,
  938. Map.Entry::getValue,
  939. ListUtils::union
  940. ) );
  941. return new ValidationResponse<>( repository, errorMap );
  942. }
  943. @Override
  944. public void configurationEvent( ConfigurationEvent event )
  945. {
  946. // We ignore the event, if the save was triggered by ourself
  947. if ( !ConfigurationHandler.REGISTRY_EVENT_TAG.equals( event.getTag( ) ) )
  948. {
  949. reload( );
  950. }
  951. }
  952. @Override
  953. public <T extends Event> void registerEventHandler( EventType<T> type, EventHandler<? super T> eventHandler )
  954. {
  955. eventManager.registerEventHandler( type, eventHandler );
  956. }
  957. @Override
  958. public <T extends Event> void unregisterEventHandler( EventType<T> type, EventHandler<? super T> eventHandler )
  959. {
  960. eventManager.unregisterEventHandler( type, eventHandler );
  961. }
  962. @Override
  963. public void handle( Event event )
  964. {
  965. // To avoid event cycles:
  966. if ( sameOriginator( event ) )
  967. {
  968. return;
  969. }
  970. if ( event instanceof RepositoryIndexEvent )
  971. {
  972. handleIndexCreationEvent( (RepositoryIndexEvent) event );
  973. }
  974. // We propagate all events to our listeners, but with context of repository registry
  975. pushEvent( event );
  976. }
  977. private void handleIndexCreationEvent( RepositoryIndexEvent event )
  978. {
  979. if (!ignoreIndexing && !( event.getRepository() instanceof ManagedRepository ))
  980. {
  981. EditableRepository repo = (EditableRepository) event.getRepository( );
  982. if ( repo != null )
  983. {
  984. ArchivaIndexManager idxmgr = getIndexManager( repo.getType( ) );
  985. if ( repo.getIndexingContext( ) != null )
  986. {
  987. try
  988. {
  989. ArchivaIndexingContext newCtx = idxmgr.move( repo.getIndexingContext( ), repo );
  990. repo.setIndexingContext( newCtx );
  991. idxmgr.updateLocalIndexPath( repo );
  992. }
  993. catch ( IndexCreationFailedException e )
  994. {
  995. log.error( "Could not move index to new directory: '{}'", e.getMessage( ), e );
  996. }
  997. }
  998. else
  999. {
  1000. try
  1001. {
  1002. ArchivaIndexingContext context = idxmgr.createContext( repo );
  1003. repo.setIndexingContext( context );
  1004. idxmgr.updateLocalIndexPath( repo );
  1005. }
  1006. catch ( IndexCreationFailedException e )
  1007. {
  1008. log.error( "Could not create index: '{}'", e.getMessage( ), e );
  1009. }
  1010. }
  1011. }
  1012. }
  1013. }
  1014. private boolean sameOriginator( Event event )
  1015. {
  1016. if ( event.getSource( ) == this )
  1017. {
  1018. return true;
  1019. }
  1020. else if ( event.hasPreviousEvent( ) )
  1021. {
  1022. return sameOriginator( event.getPreviousEvent( ) );
  1023. }
  1024. else
  1025. {
  1026. return false;
  1027. }
  1028. }
  1029. private void pushEvent( Event event )
  1030. {
  1031. eventManager.fireEvent( event );
  1032. }
  1033. private <R extends Repository, C extends AbstractRepositoryConfiguration> void doRegister( RepositoryHandler<R, C> repositoryHandler )
  1034. {
  1035. repositoryHandler.setRepositoryProviders( this.repositoryProviders );
  1036. repositoryHandler.setRepositoryValidator( this.repositoryValidatorList );
  1037. }
  1038. @SuppressWarnings( "unchecked" )
  1039. @Override
  1040. public void registerHandler( RepositoryHandler<?, ?> handler )
  1041. {
  1042. if ( handler.getVariant( ).isAssignableFrom( RepositoryGroup.class ) )
  1043. {
  1044. registerGroupHandler( (RepositoryHandler<RepositoryGroup, RepositoryGroupConfiguration>) handler );
  1045. }
  1046. else if ( handler.getVariant( ).isAssignableFrom( ManagedRepository.class ) )
  1047. {
  1048. registerManagedRepositoryHandler( (RepositoryHandler<ManagedRepository, ManagedRepositoryConfiguration>) handler );
  1049. }
  1050. else if ( handler.getVariant().isAssignableFrom( RemoteRepository.class )) {
  1051. registerRemoteRepositoryHandler( (RepositoryHandler<RemoteRepository, RemoteRepositoryConfiguration>) handler );
  1052. }
  1053. }
  1054. @Override
  1055. public boolean isRegisteredId( String id )
  1056. {
  1057. return hasRepository( id );
  1058. }
  1059. @SuppressWarnings( "unchecked" )
  1060. @Override
  1061. public <R extends Repository, C extends AbstractRepositoryConfiguration> RepositoryHandler<R, C> getHandler( Class<R> repositoryClazz, Class<C> configurationClazz )
  1062. {
  1063. if ( repositoryClazz.isAssignableFrom( RepositoryGroup.class ) )
  1064. {
  1065. return (RepositoryHandler<R, C>) this.groupHandler;
  1066. }
  1067. else if ( repositoryClazz.isAssignableFrom( ManagedRepository.class ) )
  1068. {
  1069. return (RepositoryHandler<R, C>) this.managedRepositoryHandler;
  1070. }
  1071. else if ( repositoryClazz.isAssignableFrom( RemoteRepository.class )) {
  1072. return (RepositoryHandler<R, C>) this.remoteRepositoryHandler;
  1073. }
  1074. else
  1075. {
  1076. return null;
  1077. }
  1078. }
  1079. public boolean isIgnoreIndexing( )
  1080. {
  1081. return ignoreIndexing;
  1082. }
  1083. public void setIgnoreIndexing( boolean ignoreIndexing )
  1084. {
  1085. this.ignoreIndexing = ignoreIndexing;
  1086. }
  1087. }