001package org.apache.archiva.repository.base; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import org.apache.archiva.configuration.*; 023import org.apache.archiva.event.Event; 024import org.apache.archiva.event.EventManager; 025import org.apache.archiva.event.EventType; 026import org.apache.archiva.indexer.*; 027import org.apache.archiva.components.registry.RegistryException; 028import org.apache.archiva.repository.EditableManagedRepository; 029import org.apache.archiva.repository.EditableRemoteRepository; 030import org.apache.archiva.repository.EditableRepository; 031import org.apache.archiva.repository.EditableRepositoryGroup; 032import org.apache.archiva.repository.ManagedRepository; 033import org.apache.archiva.repository.RemoteRepository; 034import org.apache.archiva.repository.Repository; 035import org.apache.archiva.repository.RepositoryContentFactory; 036import org.apache.archiva.repository.RepositoryException; 037import org.apache.archiva.repository.RepositoryGroup; 038import org.apache.archiva.repository.RepositoryProvider; 039import org.apache.archiva.repository.RepositoryRegistry; 040import org.apache.archiva.repository.RepositoryType; 041import org.apache.archiva.repository.event.*; 042import org.apache.archiva.event.EventHandler; 043import org.apache.archiva.repository.features.IndexCreationFeature; 044import org.apache.archiva.repository.features.StagingRepositoryFeature; 045import org.apache.commons.lang3.StringUtils; 046import org.slf4j.Logger; 047import org.slf4j.LoggerFactory; 048import org.springframework.stereotype.Service; 049 050import javax.annotation.PostConstruct; 051import javax.annotation.PreDestroy; 052import javax.inject.Inject; 053import javax.inject.Named; 054import java.util.*; 055import java.util.concurrent.locks.ReentrantReadWriteLock; 056import java.util.stream.Collectors; 057import java.util.stream.Stream; 058 059import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH; 060 061/** 062 * Registry for repositories. This is the central entry point for repositories. It provides methods for 063 * retrieving, adding and removing repositories. 064 * <p> 065 * The modification methods addXX and removeXX persist the changes immediately to the configuration. If the 066 * configuration save fails the changes are rolled back. 067 * <p> 068 * TODO: Audit events 069 * 070 * @since 3.0 071 */ 072@Service("repositoryRegistry") 073public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHandler<Event>, 074 RepositoryRegistry 075{ 076 077 private static final Logger log = LoggerFactory.getLogger(RepositoryRegistry.class); 078 079 /** 080 * We inject all repository providers 081 */ 082 @Inject 083 List<RepositoryProvider> repositoryProviders; 084 085 @Inject 086 IndexManagerFactory indexManagerFactory; 087 088 @Inject 089 ArchivaConfiguration archivaConfiguration; 090 091 @Inject 092 @Named("repositoryContentFactory#default") 093 RepositoryContentFactory repositoryContentFactory; 094 095 private final EventManager eventManager; 096 097 098 private Map<String, ManagedRepository> managedRepositories = new HashMap<>(); 099 private Map<String, ManagedRepository> uManagedRepository = Collections.unmodifiableMap(managedRepositories); 100 101 private Map<String, RemoteRepository> remoteRepositories = new HashMap<>(); 102 private Map<String, RemoteRepository> uRemoteRepositories = Collections.unmodifiableMap(remoteRepositories); 103 104 private Map<String, RepositoryGroup> repositoryGroups = new HashMap<>(); 105 private Map<String, RepositoryGroup> uRepositoryGroups = Collections.unmodifiableMap(repositoryGroups); 106 107 private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); 108 109 private volatile boolean ignoreConfigEvents = false; 110 111 public ArchivaRepositoryRegistry() { 112 this.eventManager = new EventManager(this); 113 } 114 115 @Override 116 public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration ) { 117 this.archivaConfiguration = archivaConfiguration; 118 } 119 120 @PostConstruct 121 private void initialize() { 122 rwLock.writeLock().lock(); 123 try { 124 log.debug("Initializing repository registry"); 125 updateManagedRepositoriesFromConfig(); 126 updateRemoteRepositoriesFromConfig(); 127 128 repositoryGroups.clear(); 129 Map<String, RepositoryGroup> repositoryGroups = getRepositorGroupsFromConfig(); 130 this.repositoryGroups.putAll(repositoryGroups); 131 132 // archivaConfiguration.addChangeListener(this); 133 archivaConfiguration.addListener(this); 134 } finally { 135 rwLock.writeLock().unlock(); 136 } 137 pushEvent(new RepositoryRegistryEvent(RepositoryRegistryEvent.RELOADED, this)); 138 } 139 140 @PreDestroy 141 public void destroy() { 142 for (ManagedRepository rep : managedRepositories.values()) { 143 rep.close(); 144 } 145 managedRepositories.clear(); 146 for (RemoteRepository repo : remoteRepositories.values()) { 147 repo.close(); 148 } 149 remoteRepositories.clear(); 150 pushEvent(new RepositoryRegistryEvent(RepositoryRegistryEvent.DESTROYED, this)); 151 } 152 153 154 private Map<RepositoryType, RepositoryProvider> createProviderMap() { 155 Map<RepositoryType, RepositoryProvider> map = new HashMap<>(); 156 if (repositoryProviders != null) { 157 for (RepositoryProvider provider : repositoryProviders) { 158 for (RepositoryType type : provider.provides()) { 159 map.put(type, provider); 160 } 161 } 162 } 163 return map; 164 } 165 166 private RepositoryProvider getProvider(RepositoryType type) throws RepositoryException 167 { 168 return repositoryProviders.stream().filter(repositoryProvider -> repositoryProvider.provides().contains(type)).findFirst().orElseThrow(() -> new RepositoryException("Repository type cannot be handled: " + type)); 169 } 170 171 /* 172 * Updates the repositories 173 */ 174 private void updateManagedRepositoriesFromConfig() { 175 try { 176 177 Set<String> configRepoIds = new HashSet<>(); 178 List<ManagedRepositoryConfiguration> managedRepoConfigs = 179 getArchivaConfiguration().getConfiguration().getManagedRepositories(); 180 181 if (managedRepoConfigs == null) { 182 return; 183 } 184 185 for (ManagedRepositoryConfiguration repoConfig : managedRepoConfigs) { 186 ManagedRepository repo = putRepository(repoConfig, null); 187 configRepoIds.add(repoConfig.getId()); 188 if (repo.supportsFeature(StagingRepositoryFeature.class)) { 189 StagingRepositoryFeature stagF = repo.getFeature(StagingRepositoryFeature.class).get(); 190 if (stagF.getStagingRepository() != null) { 191 configRepoIds.add(stagF.getStagingRepository().getId()); 192 } 193 } 194 } 195 List<String> toRemove = managedRepositories.keySet().stream().filter(id -> !configRepoIds.contains(id)).collect(Collectors.toList()); 196 for (String id : toRemove) { 197 ManagedRepository removed = managedRepositories.remove(id); 198 removed.close(); 199 } 200 } catch (Throwable e) { 201 log.error("Could not initialize repositories from config: {}", e.getMessage(), e); 202 return; 203 } 204 } 205 206 private ManagedRepository createNewManagedRepository(RepositoryProvider provider, ManagedRepositoryConfiguration cfg) throws RepositoryException { 207 log.debug("Creating repo {}", cfg.getId()); 208 ManagedRepository repo = provider.createManagedInstance(cfg); 209 repo.registerEventHandler(RepositoryEvent.ANY, this); 210 updateRepositoryReferences(provider, repo, cfg, null); 211 return repo; 212 213 } 214 215 private String getStagingId(String repoId) { 216 return repoId + StagingRepositoryFeature.STAGING_REPO_POSTFIX; 217 } 218 219 @SuppressWarnings("unchecked") 220 private void updateRepositoryReferences(RepositoryProvider provider, ManagedRepository repo, ManagedRepositoryConfiguration cfg, Configuration configuration) throws RepositoryException { 221 log.debug("Updating references of repo {}", repo.getId()); 222 if (repo.supportsFeature(StagingRepositoryFeature.class)) { 223 StagingRepositoryFeature feature = repo.getFeature(StagingRepositoryFeature.class).get(); 224 if (feature.isStageRepoNeeded() && feature.getStagingRepository() == null) { 225 ManagedRepository stageRepo = getManagedRepository(getStagingId(repo.getId())); 226 if (stageRepo == null) { 227 stageRepo = getStagingRepository(provider, cfg, configuration); 228 managedRepositories.put(stageRepo.getId(), stageRepo); 229 if (configuration != null) { 230 replaceOrAddRepositoryConfig(provider.getManagedConfiguration(stageRepo), configuration); 231 } 232 pushEvent(new LifecycleEvent(LifecycleEvent.REGISTERED, this, stageRepo)); 233 } 234 feature.setStagingRepository(stageRepo); 235 } 236 } 237 if (repo instanceof EditableManagedRepository ) { 238 EditableManagedRepository editableRepo = (EditableManagedRepository) repo; 239 if (repo.getContent() == null) { 240 editableRepo.setContent(repositoryContentFactory.getManagedRepositoryContent(repo)); 241 editableRepo.getContent().setRepository(editableRepo); 242 } 243 log.debug("Index repo: " + repo.hasIndex()); 244 if (repo.hasIndex() && ( repo.getIndexingContext() == null || !repo.getIndexingContext().isOpen() )) { 245 log.debug("Creating indexing context for {}", repo.getId()); 246 createIndexingContext(editableRepo); 247 } 248 } 249 repo.registerEventHandler(RepositoryEvent.ANY, this); 250 } 251 252 @Override 253 public ArchivaIndexManager getIndexManager( RepositoryType type ) { 254 return indexManagerFactory.getIndexManager(type); 255 } 256 257 private void createIndexingContext( EditableRepository editableRepo) throws RepositoryException { 258 if (editableRepo.supportsFeature(IndexCreationFeature.class)) { 259 ArchivaIndexManager idxManager = getIndexManager(editableRepo.getType()); 260 try { 261 editableRepo.setIndexingContext(idxManager.createContext(editableRepo)); 262 idxManager.updateLocalIndexPath(editableRepo); 263 } catch (IndexCreationFailedException e) { 264 throw new RepositoryException("Could not create index for repository " + editableRepo.getId() + ": " + e.getMessage(), e); 265 } 266 } 267 } 268 269 private ManagedRepository getStagingRepository(RepositoryProvider provider, ManagedRepositoryConfiguration baseRepoCfg, Configuration configuration) throws RepositoryException { 270 ManagedRepository stageRepo = getManagedRepository(getStagingId(baseRepoCfg.getId())); 271 if (stageRepo == null) { 272 stageRepo = provider.createStagingInstance(baseRepoCfg); 273 if (stageRepo.supportsFeature(StagingRepositoryFeature.class)) { 274 stageRepo.getFeature(StagingRepositoryFeature.class).get().setStageRepoNeeded(false); 275 } 276 ManagedRepositoryConfiguration stageCfg = provider.getManagedConfiguration(stageRepo); 277 updateRepositoryReferences(provider, stageRepo, stageCfg, configuration); 278 } 279 return stageRepo; 280 } 281 282 283 private void updateRemoteRepositoriesFromConfig() { 284 try { 285 List<RemoteRepositoryConfiguration> remoteRepoConfigs = 286 getArchivaConfiguration().getConfiguration().getRemoteRepositories(); 287 288 if (remoteRepoConfigs == null) { 289 return; 290 } 291 Set<String> repoIds = new HashSet<>(); 292 for (RemoteRepositoryConfiguration repoConfig : remoteRepoConfigs) { 293 putRepository(repoConfig, null); 294 repoIds.add(repoConfig.getId()); 295 } 296 297 List<String> toRemove = remoteRepositories.keySet().stream().filter(id -> !repoIds.contains(id)).collect(Collectors.toList()); 298 for (String id : toRemove) { 299 RemoteRepository removed = remoteRepositories.remove(id); 300 removed.close(); 301 } 302 303 } catch (Throwable e) { 304 log.error("Could not initialize remote repositories from config: {}", e.getMessage(), e); 305 return; 306 } 307 } 308 309 private RemoteRepository createNewRemoteRepository(RepositoryProvider provider, RemoteRepositoryConfiguration cfg) throws RepositoryException { 310 log.debug("Creating remote repo {}", cfg.getId()); 311 RemoteRepository repo = provider.createRemoteInstance(cfg); 312 updateRepositoryReferences(provider, repo, cfg, null); 313 return repo; 314 315 } 316 317 private void updateRepositoryReferences(RepositoryProvider provider, RemoteRepository repo, RemoteRepositoryConfiguration cfg, Configuration configuration) throws RepositoryException { 318 if (repo instanceof EditableRemoteRepository && repo.getContent() == null) { 319 EditableRemoteRepository editableRepo = (EditableRemoteRepository) repo; 320 editableRepo.setContent(repositoryContentFactory.getRemoteRepositoryContent(repo)); 321 if (repo.supportsFeature(IndexCreationFeature.class) && repo.getIndexingContext() == null) { 322 createIndexingContext(editableRepo); 323 } 324 } 325 repo.registerEventHandler(RepositoryEvent.ANY, this); 326 } 327 328 private Map<String, RepositoryGroup> getRepositorGroupsFromConfig() { 329 try { 330 List<RepositoryGroupConfiguration> repositoryGroupConfigurations = 331 getArchivaConfiguration().getConfiguration().getRepositoryGroups(); 332 333 if (repositoryGroupConfigurations == null) { 334 return Collections.emptyMap(); 335 } 336 337 Map<String, RepositoryGroup> repositoryGroupMap = new LinkedHashMap<>(repositoryGroupConfigurations.size()); 338 339 Map<RepositoryType, RepositoryProvider> providerMap = createProviderMap(); 340 for (RepositoryGroupConfiguration repoConfig : repositoryGroupConfigurations) { 341 RepositoryType repositoryType = RepositoryType.valueOf(repoConfig.getType()); 342 if (providerMap.containsKey(repositoryType)) { 343 try { 344 RepositoryGroup repo = createNewRepositoryGroup(providerMap.get(repositoryType), repoConfig); 345 repositoryGroupMap.put(repo.getId(), repo); 346 } catch (Exception e) { 347 log.error("Could not create repository group {}: {}", repoConfig.getId(), e.getMessage(), e); 348 } 349 } 350 } 351 return repositoryGroupMap; 352 } catch (Throwable e) { 353 log.error("Could not initialize repositories from config: {}", e.getMessage(), e); 354 return Collections.emptyMap(); 355 } 356 } 357 358 private RepositoryGroup createNewRepositoryGroup(RepositoryProvider provider, RepositoryGroupConfiguration config) throws RepositoryException { 359 RepositoryGroup repositoryGroup = provider.createRepositoryGroup(config); 360 repositoryGroup.registerEventHandler(RepositoryEvent.ANY, this); 361 updateRepositoryReferences(provider, repositoryGroup, config); 362 return repositoryGroup; 363 } 364 365 private void updateRepositoryReferences(RepositoryProvider provider, RepositoryGroup group, RepositoryGroupConfiguration configuration) { 366 if (group instanceof EditableRepositoryGroup ) { 367 EditableRepositoryGroup eGroup = (EditableRepositoryGroup) group; 368 eGroup.setRepositories(configuration.getRepositories().stream().map(r -> getManagedRepository(r)).collect(Collectors.toList())); 369 } 370 } 371 372 private ArchivaConfiguration getArchivaConfiguration() { 373 return this.archivaConfiguration; 374 } 375 376 /** 377 * Returns all repositories that are registered. There is no defined order of the returned repositories. 378 * 379 * @return a list of managed and remote repositories 380 */ 381 @Override 382 public Collection<Repository> getRepositories( ) { 383 rwLock.readLock().lock(); 384 try { 385 return Stream.concat(managedRepositories.values().stream(), remoteRepositories.values().stream()).collect(Collectors.toList()); 386 } finally { 387 rwLock.readLock().unlock(); 388 } 389 } 390 391 /** 392 * Returns only the managed repositories. There is no defined order of the returned repositories. 393 * 394 * @return a list of managed repositories 395 */ 396 @Override 397 public Collection<ManagedRepository> getManagedRepositories( ) { 398 rwLock.readLock().lock(); 399 try { 400 return uManagedRepository.values(); 401 } finally { 402 rwLock.readLock().unlock(); 403 } 404 } 405 406 /** 407 * Returns only the remote repositories. There is no defined order of the returned repositories. 408 * 409 * @return a list of remote repositories 410 */ 411 @Override 412 public Collection<RemoteRepository> getRemoteRepositories( ) { 413 rwLock.readLock().lock(); 414 try { 415 return uRemoteRepositories.values(); 416 } finally { 417 rwLock.readLock().unlock(); 418 } 419 } 420 421 @Override 422 public Collection<RepositoryGroup> getRepositoryGroups( ) { 423 rwLock.readLock().lock(); 424 try { 425 return uRepositoryGroups.values(); 426 } finally { 427 rwLock.readLock().unlock(); 428 } 429 } 430 431 /** 432 * Returns the repository with the given id. The returned repository may be a managed or remote repository. 433 * It returns null, if no repository is registered with the given id. 434 * 435 * @param repoId the repository id 436 * @return the repository if found, otherwise null 437 */ 438 @Override 439 public Repository getRepository( String repoId ) { 440 rwLock.readLock().lock(); 441 try { 442 log.debug("getRepository {}", repoId); 443 if (managedRepositories.containsKey(repoId)) { 444 log.debug("Managed repo"); 445 return managedRepositories.get(repoId); 446 } else if (remoteRepositories.containsKey(repoId)) { 447 log.debug("Remote repo"); 448 return remoteRepositories.get(repoId); 449 } else if (repositoryGroups.containsKey(repoId)) { 450 return repositoryGroups.get(repoId); 451 } else { 452 return null; 453 } 454 } finally { 455 rwLock.readLock().unlock(); 456 } 457 } 458 459 /** 460 * Convenience method, that returns the managed repository with the given id. 461 * It returns null, if no managed repository is registered with this id. 462 * 463 * @param repoId the repository id 464 * @return the managed repository if found, otherwise null 465 */ 466 @Override 467 public ManagedRepository getManagedRepository( String repoId ) { 468 rwLock.readLock().lock(); 469 try { 470 return managedRepositories.get(repoId); 471 } finally { 472 rwLock.readLock().unlock(); 473 } 474 } 475 476 /** 477 * Convenience method, that returns the remote repository with the given id. 478 * It returns null, if no remote repository is registered with this id. 479 * 480 * @param repoId the repository id 481 * @return the remote repository if found, otherwise null 482 */ 483 @Override 484 public RemoteRepository getRemoteRepository( String repoId ) { 485 rwLock.readLock().lock(); 486 try { 487 return remoteRepositories.get(repoId); 488 } finally { 489 rwLock.readLock().unlock(); 490 } 491 } 492 493 @Override 494 public RepositoryGroup getRepositoryGroup( String groupId ) { 495 rwLock.readLock().lock(); 496 try { 497 return repositoryGroups.get(groupId); 498 } finally { 499 rwLock.readLock().unlock(); 500 } 501 } 502 503 /* 504 * The <code>ignoreConfigEvents</code> works only for synchronized configuration events. 505 * If the configuration throws async events, we cannot know, if the event is caused by this instance or another thread. 506 */ 507 private void saveConfiguration(Configuration configuration) throws IndeterminateConfigurationException, RegistryException { 508 ignoreConfigEvents = true; 509 try { 510 getArchivaConfiguration().save(configuration); 511 } finally { 512 ignoreConfigEvents = false; 513 } 514 } 515 516 /** 517 * Adds a new repository to the current list, or replaces the repository definition with 518 * the same id, if it exists already. 519 * The change is saved to the configuration immediately. 520 * 521 * @param managedRepository the new repository. 522 * @throws RepositoryException if the new repository could not be saved to the configuration. 523 */ 524 @Override 525 public ManagedRepository putRepository( ManagedRepository managedRepository ) throws RepositoryException { 526 rwLock.writeLock().lock(); 527 try { 528 final String id = managedRepository.getId(); 529 if (remoteRepositories.containsKey(id)) { 530 throw new RepositoryException("There exists a remote repository with id " + id + ". Could not update with managed repository."); 531 } 532 ManagedRepository originRepo = managedRepositories.put(id, managedRepository); 533 try { 534 if (originRepo != null && originRepo != managedRepository) { 535 originRepo.close(); 536 } 537 RepositoryProvider provider = getProvider(managedRepository.getType()); 538 ManagedRepositoryConfiguration newCfg = provider.getManagedConfiguration(managedRepository); 539 Configuration configuration = getArchivaConfiguration().getConfiguration(); 540 updateRepositoryReferences(provider, managedRepository, newCfg, configuration); 541 ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById(id); 542 if (oldCfg != null) { 543 configuration.removeManagedRepository(oldCfg); 544 } 545 configuration.addManagedRepository(newCfg); 546 saveConfiguration(configuration); 547 if (originRepo != managedRepository) { 548 pushEvent(new LifecycleEvent(LifecycleEvent.REGISTERED, this, managedRepository)); 549 } else { 550 pushEvent(new LifecycleEvent(LifecycleEvent.UPDATED, this, managedRepository)); 551 } 552 return managedRepository; 553 } catch (Exception e) { 554 // Rollback only partly, because repository is closed already 555 if (originRepo != null) { 556 managedRepositories.put(id, originRepo); 557 } else { 558 managedRepositories.remove(id); 559 } 560 log.error("Exception during configuration update {}", e.getMessage(), e); 561 throw new RepositoryException("Could not save the configuration" + (e.getMessage() == null ? "" : ": " + e.getMessage())); 562 } 563 } finally { 564 rwLock.writeLock().unlock(); 565 } 566 } 567 568 /** 569 * Adds a new repository or updates the repository with the same id, if it exists already. 570 * The configuration is saved immediately. 571 * 572 * @param managedRepositoryConfiguration the repository configuration 573 * @return the updated or created repository 574 * @throws RepositoryException if an error occurs, or the configuration is not valid. 575 */ 576 @Override 577 public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration ) throws RepositoryException { 578 rwLock.writeLock().lock(); 579 try { 580 final String id = managedRepositoryConfiguration.getId(); 581 final RepositoryType repositoryType = RepositoryType.valueOf(managedRepositoryConfiguration.getType()); 582 Configuration configuration = getArchivaConfiguration().getConfiguration(); 583 ManagedRepository repo = managedRepositories.get(id); 584 ManagedRepositoryConfiguration oldCfg = repo != null ? getProvider(repositoryType).getManagedConfiguration(repo) : null; 585 repo = putRepository(managedRepositoryConfiguration, configuration); 586 try { 587 saveConfiguration(configuration); 588 } catch (IndeterminateConfigurationException | RegistryException e) { 589 if (oldCfg != null) { 590 getProvider(repositoryType).updateManagedInstance((EditableManagedRepository) repo, oldCfg); 591 } 592 log.error("Could not save the configuration for repository {}: {}", id, e.getMessage(), e); 593 throw new RepositoryException("Could not save the configuration for repository " + id + ": " + e.getMessage()); 594 } 595 return repo; 596 } finally { 597 rwLock.writeLock().unlock(); 598 } 599 600 } 601 602 /** 603 * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but 604 * the configuration is not saved. 605 * 606 * @param managedRepositoryConfiguration the new or changed managed repository configuration 607 * @param configuration the configuration object (may be <code>null</code>) 608 * @return the new or updated repository 609 * @throws RepositoryException if the configuration cannot be saved or updated 610 */ 611 @Override 612 public ManagedRepository putRepository( ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration ) throws RepositoryException { 613 rwLock.writeLock().lock(); 614 try { 615 final String id = managedRepositoryConfiguration.getId(); 616 final RepositoryType repoType = RepositoryType.valueOf(managedRepositoryConfiguration.getType()); 617 ManagedRepository repo; 618 boolean registeredNew = false; 619 repo = managedRepositories.get(id); 620 if (repo != null && repo.isOpen()) { 621 if (repo instanceof EditableManagedRepository) { 622 getProvider(repoType).updateManagedInstance((EditableManagedRepository) repo, managedRepositoryConfiguration); 623 } else { 624 throw new RepositoryException("The repository is not editable " + id); 625 } 626 } else { 627 repo = getProvider(repoType).createManagedInstance(managedRepositoryConfiguration); 628 managedRepositories.put(id, repo); 629 registeredNew = true; 630 } 631 updateRepositoryReferences(getProvider(repoType), repo, managedRepositoryConfiguration, configuration); 632 replaceOrAddRepositoryConfig(managedRepositoryConfiguration, configuration); 633 if (registeredNew) { 634 pushEvent(new LifecycleEvent(LifecycleEvent.REGISTERED, this, repo)); 635 } else { 636 pushEvent(new LifecycleEvent(LifecycleEvent.UPDATED, this, repo)); 637 } 638 return repo; 639 } finally { 640 rwLock.writeLock().unlock(); 641 } 642 } 643 644 645 /** 646 * Adds a new repository group to the current list, or replaces the repository group definition with 647 * the same id, if it exists already. 648 * The change is saved to the configuration immediately. 649 * 650 * @param repositoryGroup the new repository group. 651 * @throws RepositoryException if the new repository group could not be saved to the configuration. 652 */ 653 @Override 654 public RepositoryGroup putRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException { 655 rwLock.writeLock().lock(); 656 try { 657 final String id = repositoryGroup.getId(); 658 RepositoryGroup originRepoGroup = repositoryGroups.put(id, repositoryGroup); 659 try { 660 if (originRepoGroup != null && originRepoGroup != repositoryGroup) { 661 originRepoGroup.close(); 662 } 663 RepositoryProvider provider = getProvider(repositoryGroup.getType()); 664 RepositoryGroupConfiguration newCfg = provider.getRepositoryGroupConfiguration(repositoryGroup); 665 Configuration configuration = getArchivaConfiguration().getConfiguration(); 666 updateRepositoryReferences(provider, repositoryGroup, newCfg); 667 RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById(id); 668 if (oldCfg != null) { 669 configuration.removeRepositoryGroup(oldCfg); 670 } 671 configuration.addRepositoryGroup(newCfg); 672 saveConfiguration(configuration); 673 return repositoryGroup; 674 } catch (Exception e) { 675 // Rollback 676 if (originRepoGroup != null) { 677 repositoryGroups.put(id, originRepoGroup); 678 } else { 679 repositoryGroups.remove(id); 680 } 681 log.error("Exception during configuration update {}", e.getMessage(), e); 682 throw new RepositoryException("Could not save the configuration" + (e.getMessage() == null ? "" : ": " + e.getMessage())); 683 } 684 } finally { 685 rwLock.writeLock().unlock(); 686 } 687 } 688 689 /** 690 * Adds a new repository group or updates the repository with the same id, if it exists already. 691 * The configuration is saved immediately. 692 * 693 * @param repositoryGroupConfiguration the repository configuration 694 * @return the updated or created repository 695 * @throws RepositoryException if an error occurs, or the configuration is not valid. 696 */ 697 @Override 698 public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration ) throws RepositoryException { 699 rwLock.writeLock().lock(); 700 try { 701 final String id = repositoryGroupConfiguration.getId(); 702 final RepositoryType repositoryType = RepositoryType.valueOf(repositoryGroupConfiguration.getType()); 703 Configuration configuration = getArchivaConfiguration().getConfiguration(); 704 RepositoryGroup repo = repositoryGroups.get(id); 705 RepositoryGroupConfiguration oldCfg = repo != null ? getProvider(repositoryType).getRepositoryGroupConfiguration(repo) : null; 706 repo = putRepositoryGroup(repositoryGroupConfiguration, configuration); 707 try { 708 saveConfiguration(configuration); 709 } catch (IndeterminateConfigurationException | RegistryException e) { 710 if (oldCfg != null) { 711 getProvider(repositoryType).updateRepositoryGroupInstance((EditableRepositoryGroup) repo, oldCfg); 712 } 713 log.error("Could not save the configuration for repository group {}: {}", id, e.getMessage(), e); 714 throw new RepositoryException("Could not save the configuration for repository group " + id + ": " + e.getMessage()); 715 } 716 return repo; 717 } finally { 718 rwLock.writeLock().unlock(); 719 } 720 721 } 722 723 /** 724 * Adds a new repository group or updates the repository group with the same id. The given configuration object is updated, but 725 * the configuration is not saved. 726 * 727 * @param repositoryGroupConfiguration The configuration of the new or changed repository group. 728 * @param configuration The configuration object. If it is <code>null</code>, the configuration is not saved. 729 * @return The new or updated repository group 730 * @throws RepositoryException if the configuration cannot be saved or updated 731 */ 732 @Override 733 public RepositoryGroup putRepositoryGroup( RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration ) throws RepositoryException { 734 rwLock.writeLock().lock(); 735 try { 736 final String id = repositoryGroupConfiguration.getId(); 737 final RepositoryType repoType = RepositoryType.valueOf(repositoryGroupConfiguration.getType()); 738 RepositoryGroup repo; 739 setRepositoryGroupDefaults(repositoryGroupConfiguration); 740 if (repositoryGroups.containsKey(id)) { 741 repo = repositoryGroups.get(id); 742 if (repo instanceof EditableRepositoryGroup) { 743 getProvider(repoType).updateRepositoryGroupInstance((EditableRepositoryGroup) repo, repositoryGroupConfiguration); 744 } else { 745 throw new RepositoryException("The repository is not editable " + id); 746 } 747 } else { 748 repo = getProvider(repoType).createRepositoryGroup(repositoryGroupConfiguration); 749 repositoryGroups.put(id, repo); 750 } 751 updateRepositoryReferences(getProvider(repoType), repo, repositoryGroupConfiguration); 752 replaceOrAddRepositoryConfig(repositoryGroupConfiguration, configuration); 753 return repo; 754 } finally { 755 rwLock.writeLock().unlock(); 756 } 757 } 758 759 private void setRepositoryGroupDefaults(RepositoryGroupConfiguration repositoryGroupConfiguration) { 760 if (StringUtils.isEmpty(repositoryGroupConfiguration.getMergedIndexPath())) { 761 repositoryGroupConfiguration.setMergedIndexPath(DEFAULT_INDEX_PATH); 762 } 763 if (repositoryGroupConfiguration.getMergedIndexTtl() <= 0) { 764 repositoryGroupConfiguration.setMergedIndexTtl(300); 765 } 766 if (StringUtils.isEmpty(repositoryGroupConfiguration.getCronExpression())) { 767 repositoryGroupConfiguration.setCronExpression("0 0 03 ? * MON"); 768 } 769 } 770 771 private void replaceOrAddRepositoryConfig(ManagedRepositoryConfiguration managedRepositoryConfiguration, Configuration configuration) { 772 if (configuration != null) { 773 ManagedRepositoryConfiguration oldCfg = configuration.findManagedRepositoryById(managedRepositoryConfiguration.getId()); 774 if (oldCfg != null) { 775 configuration.removeManagedRepository(oldCfg); 776 } 777 configuration.addManagedRepository(managedRepositoryConfiguration); 778 } 779 } 780 781 private void replaceOrAddRepositoryConfig(RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration) { 782 if (configuration != null) { 783 RemoteRepositoryConfiguration oldCfg = configuration.findRemoteRepositoryById(remoteRepositoryConfiguration.getId()); 784 if (oldCfg != null) { 785 configuration.removeRemoteRepository(oldCfg); 786 } 787 configuration.addRemoteRepository(remoteRepositoryConfiguration); 788 } 789 } 790 791 private void replaceOrAddRepositoryConfig(RepositoryGroupConfiguration repositoryGroupConfiguration, Configuration configuration) { 792 RepositoryGroupConfiguration oldCfg = configuration.findRepositoryGroupById(repositoryGroupConfiguration.getId()); 793 if (oldCfg != null) { 794 configuration.removeRepositoryGroup(oldCfg); 795 } 796 configuration.addRepositoryGroup(repositoryGroupConfiguration); 797 } 798 799 @Override 800 public RemoteRepository putRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException { 801 rwLock.writeLock().lock(); 802 try { 803 final String id = remoteRepository.getId(); 804 if (managedRepositories.containsKey(id)) { 805 throw new RepositoryException("There exists a managed repository with id " + id + ". Could not update with remote repository."); 806 } 807 RemoteRepository originRepo = remoteRepositories.put(id, remoteRepository); 808 RemoteRepositoryConfiguration oldCfg = null; 809 RemoteRepositoryConfiguration newCfg; 810 try { 811 if (originRepo != null && originRepo != remoteRepository) { 812 originRepo.close(); 813 } 814 final RepositoryProvider provider = getProvider(remoteRepository.getType()); 815 newCfg = provider.getRemoteConfiguration(remoteRepository); 816 updateRepositoryReferences(provider, remoteRepository, newCfg, configuration); 817 oldCfg = configuration.findRemoteRepositoryById(id); 818 if (oldCfg != null) { 819 configuration.removeRemoteRepository(oldCfg); 820 } 821 configuration.addRemoteRepository(newCfg); 822 if (remoteRepository != originRepo) { 823 pushEvent(new LifecycleEvent(LifecycleEvent.REGISTERED, this, remoteRepository)); 824 } else { 825 pushEvent(new LifecycleEvent(LifecycleEvent.UPDATED, this, remoteRepository)); 826 } 827 return remoteRepository; 828 } catch (Exception e) { 829 // Rollback 830 if (originRepo != null) { 831 remoteRepositories.put(id, originRepo); 832 } else { 833 remoteRepositories.remove(id); 834 } 835 if (oldCfg != null) { 836 RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById(id); 837 if (cfg != null) { 838 configuration.removeRemoteRepository(cfg); 839 configuration.addRemoteRepository(oldCfg); 840 } 841 } 842 log.error("Error while adding remote repository {}", e.getMessage(), e); 843 throw new RepositoryException("Could not save the configuration" + (e.getMessage() == null ? "" : ": " + e.getMessage())); 844 } 845 } finally { 846 rwLock.writeLock().unlock(); 847 } 848 } 849 850 /** 851 * Adds a remote repository, or overwrites the repository definition with the same id, if it exists already. 852 * The modification is saved to the configuration immediately. 853 * 854 * @param remoteRepository the remote repository to add 855 * @throws RepositoryException if an error occurs during configuration save 856 */ 857 @Override 858 public RemoteRepository putRepository( RemoteRepository remoteRepository ) throws RepositoryException { 859 rwLock.writeLock().lock(); 860 try { 861 Configuration configuration = getArchivaConfiguration().getConfiguration(); 862 try { 863 RemoteRepository repo = putRepository(remoteRepository, configuration); 864 saveConfiguration(configuration); 865 return repo; 866 } catch (RegistryException | IndeterminateConfigurationException e) { 867 log.error("Error while saving remote repository {}", e.getMessage(), e); 868 throw new RepositoryException("Could not save the configuration" + (e.getMessage() == null ? "" : ": " + e.getMessage())); 869 } 870 } finally { 871 rwLock.writeLock().unlock(); 872 } 873 } 874 875 /** 876 * Adds a new repository or updates the repository with the same id, if it exists already. 877 * The configuration is saved immediately. 878 * 879 * @param remoteRepositoryConfiguration the repository configuration 880 * @return the updated or created repository 881 * @throws RepositoryException if an error occurs, or the configuration is not valid. 882 */ 883 @Override 884 public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration ) throws RepositoryException { 885 rwLock.writeLock().lock(); 886 try { 887 final String id = remoteRepositoryConfiguration.getId(); 888 final RepositoryType repositoryType = RepositoryType.valueOf(remoteRepositoryConfiguration.getType()); 889 Configuration configuration = getArchivaConfiguration().getConfiguration(); 890 RemoteRepository repo = remoteRepositories.get(id); 891 RemoteRepositoryConfiguration oldCfg = repo != null ? getProvider(repositoryType).getRemoteConfiguration(repo) : null; 892 repo = putRepository(remoteRepositoryConfiguration, configuration); 893 try { 894 saveConfiguration(configuration); 895 } catch (IndeterminateConfigurationException | RegistryException e) { 896 if (oldCfg != null) { 897 getProvider(repositoryType).updateRemoteInstance((EditableRemoteRepository) repo, oldCfg); 898 } 899 log.error("Could not save the configuration for repository {}: {}", id, e.getMessage(), e); 900 throw new RepositoryException("Could not save the configuration for repository " + id + ": " + e.getMessage()); 901 } 902 return repo; 903 } finally { 904 rwLock.writeLock().unlock(); 905 } 906 907 } 908 909 /** 910 * Adds a new repository or updates the repository with the same id. The given configuration object is updated, but 911 * the configuration is not saved. 912 * 913 * @param remoteRepositoryConfiguration the new or changed repository configuration 914 * @param configuration the configuration object 915 * @return the new or updated repository 916 * @throws RepositoryException if the configuration cannot be saved or updated 917 */ 918 @Override 919 @SuppressWarnings("unchecked") 920 public RemoteRepository putRepository( RemoteRepositoryConfiguration remoteRepositoryConfiguration, Configuration configuration ) throws RepositoryException { 921 rwLock.writeLock().lock(); 922 try { 923 final String id = remoteRepositoryConfiguration.getId(); 924 final RepositoryType repoType = RepositoryType.valueOf(remoteRepositoryConfiguration.getType()); 925 RemoteRepository repo; 926 boolean registeredNew = false; 927 repo = remoteRepositories.get(id); 928 if (repo != null && repo.isOpen()) { 929 if (repo instanceof EditableRemoteRepository) { 930 getProvider(repoType).updateRemoteInstance((EditableRemoteRepository) repo, remoteRepositoryConfiguration); 931 } else { 932 throw new RepositoryException("The repository is not editable " + id); 933 } 934 } else { 935 repo = getProvider(repoType).createRemoteInstance(remoteRepositoryConfiguration); 936 remoteRepositories.put(id, repo); 937 registeredNew = true; 938 } 939 updateRepositoryReferences(getProvider(repoType), repo, remoteRepositoryConfiguration, configuration); 940 replaceOrAddRepositoryConfig(remoteRepositoryConfiguration, configuration); 941 if (registeredNew) { 942 pushEvent(new LifecycleEvent(LifecycleEvent.REGISTERED, this, repo)); 943 } else { 944 pushEvent(new LifecycleEvent(LifecycleEvent.UPDATED, this, repo)); 945 } 946 return repo; 947 } finally { 948 rwLock.writeLock().unlock(); 949 } 950 951 952 } 953 954 @Override 955 public void removeRepository( String repoId ) throws RepositoryException { 956 Repository repo = getRepository(repoId); 957 if (repo != null) { 958 removeRepository(repo); 959 } 960 } 961 962 @Override 963 public void removeRepository( Repository repo ) throws RepositoryException { 964 if (repo == null) { 965 log.warn("Trying to remove null repository"); 966 return; 967 } 968 if (repo instanceof RemoteRepository) { 969 removeRepository((RemoteRepository) repo); 970 } else if (repo instanceof ManagedRepository) { 971 removeRepository((ManagedRepository) repo); 972 } else if (repo instanceof RepositoryGroup) { 973 removeRepositoryGroup((RepositoryGroup) repo); 974 } else { 975 throw new RepositoryException("Repository type not known: " + repo.getClass()); 976 } 977 } 978 979 /** 980 * Removes a managed repository from the registry and configuration, if it exists. 981 * The change is saved to the configuration immediately. 982 * 983 * @param managedRepository the managed repository to remove 984 * @throws RepositoryException if a error occurs during configuration save 985 */ 986 @Override 987 public void removeRepository( ManagedRepository managedRepository ) throws RepositoryException { 988 if (managedRepository == null) { 989 return; 990 } 991 final String id = managedRepository.getId(); 992 ManagedRepository repo = getManagedRepository(id); 993 if (repo != null) { 994 rwLock.writeLock().lock(); 995 try { 996 repo = managedRepositories.remove(id); 997 if (repo != null) { 998 repo.close(); 999 removeRepositoryFromGroups(repo); 1000 Configuration configuration = getArchivaConfiguration().getConfiguration(); 1001 ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById(id); 1002 if (cfg != null) { 1003 configuration.removeManagedRepository(cfg); 1004 } 1005 saveConfiguration(configuration); 1006 } 1007 pushEvent(new LifecycleEvent(LifecycleEvent.UNREGISTERED, this, repo)); 1008 } catch (RegistryException | IndeterminateConfigurationException e) { 1009 // Rollback 1010 log.error("Could not save config after repository removal: {}", e.getMessage(), e); 1011 managedRepositories.put(repo.getId(), repo); 1012 throw new RepositoryException("Could not save configuration after repository removal: " + e.getMessage()); 1013 } finally { 1014 rwLock.writeLock().unlock(); 1015 } 1016 } 1017 } 1018 1019 private void removeRepositoryFromGroups(ManagedRepository repo) { 1020 if (repo != null) { 1021 repositoryGroups.values().stream().filter(repoGroup -> repoGroup instanceof EditableRepository). 1022 map(repoGroup -> (EditableRepositoryGroup) repoGroup).forEach(repoGroup -> repoGroup.removeRepository(repo)); 1023 } 1024 } 1025 1026 @Override 1027 public void removeRepository( ManagedRepository managedRepository, Configuration configuration ) throws RepositoryException { 1028 if (managedRepository == null) { 1029 return; 1030 } 1031 final String id = managedRepository.getId(); 1032 ManagedRepository repo = getManagedRepository(id); 1033 if (repo != null) { 1034 rwLock.writeLock().lock(); 1035 try { 1036 repo = managedRepositories.remove(id); 1037 if (repo != null) { 1038 repo.close(); 1039 removeRepositoryFromGroups(repo); 1040 ManagedRepositoryConfiguration cfg = configuration.findManagedRepositoryById(id); 1041 if (cfg != null) { 1042 configuration.removeManagedRepository(cfg); 1043 } 1044 } 1045 pushEvent(new LifecycleEvent(LifecycleEvent.UNREGISTERED, this, repo)); 1046 } finally { 1047 rwLock.writeLock().unlock(); 1048 } 1049 } 1050 1051 } 1052 1053 1054 /** 1055 * Removes a repository group from the registry and configuration, if it exists. 1056 * The change is saved to the configuration immediately. 1057 * 1058 * @param repositoryGroup the repository group to remove 1059 * @throws RepositoryException if a error occurs during configuration save 1060 */ 1061 @Override 1062 public void removeRepositoryGroup( RepositoryGroup repositoryGroup ) throws RepositoryException { 1063 if (repositoryGroup == null) { 1064 return; 1065 } 1066 final String id = repositoryGroup.getId(); 1067 RepositoryGroup repo = getRepositoryGroup(id); 1068 if (repo != null) { 1069 rwLock.writeLock().lock(); 1070 try { 1071 repo = repositoryGroups.remove(id); 1072 if (repo != null) { 1073 repo.close(); 1074 Configuration configuration = getArchivaConfiguration().getConfiguration(); 1075 RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById(id); 1076 if (cfg != null) { 1077 configuration.removeRepositoryGroup(cfg); 1078 } 1079 saveConfiguration(configuration); 1080 } 1081 1082 } catch (RegistryException | IndeterminateConfigurationException e) { 1083 // Rollback 1084 log.error("Could not save config after repository removal: {}", e.getMessage(), e); 1085 repositoryGroups.put(repo.getId(), repo); 1086 throw new RepositoryException("Could not save configuration after repository removal: " + e.getMessage()); 1087 } finally { 1088 rwLock.writeLock().unlock(); 1089 } 1090 } 1091 } 1092 1093 @Override 1094 public void removeRepositoryGroup( RepositoryGroup repositoryGroup, Configuration configuration ) throws RepositoryException { 1095 if (repositoryGroup == null) { 1096 return; 1097 } 1098 final String id = repositoryGroup.getId(); 1099 RepositoryGroup repo = getRepositoryGroup(id); 1100 if (repo != null) { 1101 rwLock.writeLock().lock(); 1102 try { 1103 repo = repositoryGroups.remove(id); 1104 if (repo != null) { 1105 repo.close(); 1106 RepositoryGroupConfiguration cfg = configuration.findRepositoryGroupById(id); 1107 if (cfg != null) { 1108 configuration.removeRepositoryGroup(cfg); 1109 } 1110 } 1111 } finally { 1112 rwLock.writeLock().unlock(); 1113 } 1114 } 1115 1116 } 1117 1118 private void doRemoveRepo(RemoteRepository repo, Configuration configuration) { 1119 repo.close(); 1120 RemoteRepositoryConfiguration cfg = configuration.findRemoteRepositoryById(repo.getId()); 1121 if (cfg != null) { 1122 configuration.removeRemoteRepository(cfg); 1123 } 1124 List<ProxyConnectorConfiguration> proxyConnectors = new ArrayList<>(configuration.getProxyConnectors()); 1125 for (ProxyConnectorConfiguration proxyConnector : proxyConnectors) { 1126 if (StringUtils.equals(proxyConnector.getTargetRepoId(), repo.getId())) { 1127 configuration.removeProxyConnector(proxyConnector); 1128 } 1129 } 1130 } 1131 1132 /** 1133 * Removes the remote repository from the registry and configuration. 1134 * The change is saved to the configuration immediately. 1135 * 1136 * @param remoteRepository the remote repository to remove 1137 * @throws RepositoryException if a error occurs during configuration save 1138 */ 1139 @Override 1140 public void removeRepository( RemoteRepository remoteRepository ) throws RepositoryException { 1141 if (remoteRepository == null) { 1142 return; 1143 } 1144 final String id = remoteRepository.getId(); 1145 RemoteRepository repo = getRemoteRepository(id); 1146 if (repo != null) { 1147 rwLock.writeLock().lock(); 1148 try { 1149 repo = remoteRepositories.remove(id); 1150 if (repo != null) { 1151 Configuration configuration = getArchivaConfiguration().getConfiguration(); 1152 doRemoveRepo(repo, configuration); 1153 saveConfiguration(configuration); 1154 } 1155 pushEvent(new LifecycleEvent(LifecycleEvent.UNREGISTERED, this, repo)); 1156 } catch (RegistryException | IndeterminateConfigurationException e) { 1157 // Rollback 1158 log.error("Could not save config after repository removal: {}", e.getMessage(), e); 1159 remoteRepositories.put(repo.getId(), repo); 1160 throw new RepositoryException("Could not save configuration after repository removal: " + e.getMessage()); 1161 } finally { 1162 rwLock.writeLock().unlock(); 1163 } 1164 } 1165 } 1166 1167 @Override 1168 public void removeRepository( RemoteRepository remoteRepository, Configuration configuration ) throws RepositoryException { 1169 if (remoteRepository == null) { 1170 return; 1171 } 1172 final String id = remoteRepository.getId(); 1173 RemoteRepository repo = getRemoteRepository(id); 1174 if (repo != null) { 1175 rwLock.writeLock().lock(); 1176 try { 1177 repo = remoteRepositories.remove(id); 1178 if (repo != null) { 1179 doRemoveRepo(repo, configuration); 1180 } 1181 pushEvent(new LifecycleEvent(LifecycleEvent.UNREGISTERED, this, repo)); 1182 } finally { 1183 rwLock.writeLock().unlock(); 1184 } 1185 } 1186 1187 } 1188 1189 /** 1190 * Reloads the registry from the configuration. 1191 */ 1192 @Override 1193 public void reload( ) { 1194 initialize(); 1195 } 1196 1197 /** 1198 * Resets the indexing context of a given repository. 1199 * 1200 * @param repository The repository 1201 * @throws IndexUpdateFailedException If the index could not be resetted. 1202 */ 1203 @Override 1204 public void resetIndexingContext( Repository repository ) throws IndexUpdateFailedException { 1205 if (repository.hasIndex() && repository instanceof EditableRepository) { 1206 EditableRepository eRepo = (EditableRepository) repository; 1207 ArchivaIndexingContext newCtx = getIndexManager(repository.getType()).reset(repository.getIndexingContext()); 1208 eRepo.setIndexingContext(newCtx); 1209 } 1210 } 1211 1212 1213 /** 1214 * Creates a new repository instance with the same settings as this one. The cloned repository is not 1215 * registered or saved to the configuration. 1216 * 1217 * @param repo The origin repository 1218 * @return The cloned repository. 1219 */ 1220 @Override 1221 public ManagedRepository clone( ManagedRepository repo, String newId ) throws RepositoryException { 1222 if (managedRepositories.containsKey(newId) || remoteRepositories.containsKey(newId)) { 1223 throw new RepositoryException("The given id exists already " + newId); 1224 } 1225 RepositoryProvider provider = getProvider(repo.getType()); 1226 ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration(repo); 1227 cfg.setId(newId); 1228 ManagedRepository cloned = provider.createManagedInstance(cfg); 1229 cloned.registerEventHandler(RepositoryEvent.ANY, this); 1230 return cloned; 1231 } 1232 1233 @Override 1234 public <T extends Repository> Repository clone( T repo, String newId ) throws RepositoryException { 1235 if (repo instanceof RemoteRepository) { 1236 return this.clone((RemoteRepository) repo, newId); 1237 } else if (repo instanceof ManagedRepository) { 1238 return this.clone((ManagedRepository) repo, newId); 1239 } else { 1240 throw new RepositoryException("This repository class is not supported " + repo.getClass().getName()); 1241 } 1242 } 1243 1244 /** 1245 * Creates a new repository instance with the same settings as this one. The cloned repository is not 1246 * registered or saved to the configuration. 1247 * 1248 * @param repo The origin repository 1249 * @return The cloned repository. 1250 */ 1251 @Override 1252 public RemoteRepository clone( RemoteRepository repo, String newId ) throws RepositoryException { 1253 if (managedRepositories.containsKey(newId) || remoteRepositories.containsKey(newId)) { 1254 throw new RepositoryException("The given id exists already " + newId); 1255 } 1256 RepositoryProvider provider = getProvider(repo.getType()); 1257 RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration(repo); 1258 cfg.setId(newId); 1259 RemoteRepository cloned = provider.createRemoteInstance(cfg); 1260 cloned.registerEventHandler(RepositoryEvent.ANY, this); 1261 return cloned; 1262 } 1263 1264 1265 @Override 1266 public void configurationEvent(ConfigurationEvent event) { 1267 // Note: the ignoreConfigEvents flag does not work, if the config events are asynchronous. 1268 if (!ignoreConfigEvents) { 1269 reload(); 1270 } 1271 } 1272 1273 1274 @Override 1275 public <T extends Event> void registerEventHandler( EventType<T> type, EventHandler<? super T> eventHandler) { 1276 eventManager.registerEventHandler(type, eventHandler); 1277 } 1278 1279 1280 @Override 1281 public <T extends Event> void unregisterEventHandler(EventType<T> type, EventHandler<? super T> eventHandler) { 1282 eventManager.unregisterEventHandler(type, eventHandler); 1283 } 1284 1285 1286 @Override 1287 public void handle(Event event) { 1288 // To avoid event cycles: 1289 if (sameOriginator(event)) { 1290 return; 1291 } 1292 if (event instanceof RepositoryIndexEvent) { 1293 handleIndexCreationEvent((RepositoryIndexEvent) event); 1294 } 1295 // We propagate all events to our listeners, but with context of repository registry 1296 pushEvent(event); 1297 } 1298 1299 private void handleIndexCreationEvent(RepositoryIndexEvent event) { 1300 RepositoryIndexEvent idxEvent = event; 1301 if (managedRepositories.containsKey(idxEvent.getRepository().getId()) || 1302 remoteRepositories.containsKey(idxEvent.getRepository().getId())) { 1303 EditableRepository repo = (EditableRepository) idxEvent.getRepository(); 1304 if (repo != null && repo.getIndexingContext() != null) { 1305 try { 1306 ArchivaIndexManager idxmgr = getIndexManager(repo.getType()); 1307 if (idxmgr != null) { 1308 ArchivaIndexingContext newCtx = idxmgr.move(repo.getIndexingContext(), repo); 1309 repo.setIndexingContext(newCtx); 1310 idxmgr.updateLocalIndexPath(repo); 1311 } 1312 1313 } catch (IndexCreationFailedException e) { 1314 log.error("Could not move index to new directory {}", e.getMessage(), e); 1315 } 1316 } 1317 } 1318 } 1319 1320 private boolean sameOriginator(Event event) { 1321 if (event.getSource() == this) { 1322 return true; 1323 } else if (event.hasPreviousEvent()) { 1324 return sameOriginator(event.getPreviousEvent()); 1325 } else { 1326 return false; 1327 } 1328 } 1329 1330 private void pushEvent(Event event) { 1331 eventManager.fireEvent(event); 1332 } 1333 1334 1335 1336}