001 package org.apache.archiva.configuration; 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 022 import org.apache.archiva.configuration.functors.ProxyConnectorConfigurationOrderComparator; 023 import org.apache.archiva.configuration.io.registry.ConfigurationRegistryReader; 024 import org.apache.archiva.configuration.io.registry.ConfigurationRegistryWriter; 025 import org.apache.archiva.policies.AbstractUpdatePolicy; 026 import org.apache.archiva.policies.CachedFailuresPolicy; 027 import org.apache.archiva.policies.ChecksumPolicy; 028 import org.apache.archiva.policies.DownloadErrorPolicy; 029 import org.apache.archiva.policies.Policy; 030 import org.apache.archiva.policies.PostDownloadPolicy; 031 import org.apache.archiva.policies.PreDownloadPolicy; 032 import org.apache.archiva.redback.components.evaluator.DefaultExpressionEvaluator; 033 import org.apache.archiva.redback.components.evaluator.EvaluatorException; 034 import org.apache.archiva.redback.components.evaluator.ExpressionEvaluator; 035 import org.apache.archiva.redback.components.evaluator.sources.SystemPropertyExpressionSource; 036 import org.apache.archiva.redback.components.registry.Registry; 037 import org.apache.archiva.redback.components.registry.RegistryException; 038 import org.apache.archiva.redback.components.registry.RegistryListener; 039 import org.apache.archiva.redback.components.registry.commons.CommonsConfigurationRegistry; 040 import org.apache.archiva.redback.components.springutils.ComponentContainer; 041 import org.apache.commons.collections.CollectionUtils; 042 import org.apache.commons.collections.ListUtils; 043 import org.apache.commons.collections.MapUtils; 044 import org.apache.commons.configuration.BaseConfiguration; 045 import org.apache.commons.io.FileUtils; 046 import org.apache.commons.lang.StringUtils; 047 import org.slf4j.Logger; 048 import org.slf4j.LoggerFactory; 049 import org.springframework.stereotype.Service; 050 051 import javax.annotation.PostConstruct; 052 import javax.inject.Inject; 053 import javax.inject.Named; 054 import java.io.File; 055 import java.io.IOException; 056 import java.util.ArrayList; 057 import java.util.Arrays; 058 import java.util.Collection; 059 import java.util.Collections; 060 import java.util.HashMap; 061 import java.util.HashSet; 062 import java.util.Iterator; 063 import java.util.List; 064 import java.util.Map; 065 import java.util.Map.Entry; 066 import java.util.Set; 067 068 /** 069 * <p> 070 * Implementation of configuration holder that retrieves it from the registry. 071 * </p> 072 * <p> 073 * The registry layers and merges the 2 configuration files: user, and application server. 074 * </p> 075 * <p> 076 * Instead of relying on the model defaults, if the registry is empty a default configuration file is loaded and 077 * applied from a resource. The defaults are not loaded into the registry as the lists (eg repositories) could no longer 078 * be removed if that was the case. 079 * </p> 080 * <p> 081 * When saving the configuration, it is saved to the location it was read from. If it was read from the defaults, it 082 * will be saved to the user location. 083 * However, if the configuration contains information from both sources, an exception is raised as this is currently 084 * unsupported. The reason for this is that it is not possible to identify where to re-save elements, and can result 085 * in list configurations (eg repositories) becoming inconsistent. 086 * </p> 087 * <p> 088 * If the configuration is outdated, it will be upgraded when it is loaded. This is done by checking the version flag 089 * before reading it from the registry. 090 * </p> 091 */ 092 @Service ( "archivaConfiguration#default" ) 093 public class DefaultArchivaConfiguration 094 implements ArchivaConfiguration, RegistryListener 095 { 096 private Logger log = LoggerFactory.getLogger( DefaultArchivaConfiguration.class ); 097 098 /** 099 * Plexus registry to read the configuration from. 100 */ 101 @Inject 102 @Named ( value = "commons-configuration" ) 103 private Registry registry; 104 105 @Inject 106 private ComponentContainer componentContainer; 107 108 /** 109 * The configuration that has been converted. 110 */ 111 private Configuration configuration; 112 113 /** 114 * see #initialize 115 * 116 * @todo these don't strictly belong in here 117 */ 118 private Map<String, PreDownloadPolicy> prePolicies; 119 120 /** 121 * see #initialize 122 * 123 * @todo these don't strictly belong in here 124 */ 125 private Map<String, PostDownloadPolicy> postPolicies; 126 127 /** 128 * see #initialize 129 * 130 * @todo these don't strictly belong in here 131 */ 132 private Map<String, DownloadErrorPolicy> downloadErrorPolicies; 133 134 135 /** 136 * see #initialize 137 * default-value="${user.home}/.m2/archiva.xml" 138 */ 139 private String userConfigFilename = "${user.home}/.m2/archiva.xml"; 140 141 /** 142 * see #initialize 143 * default-value="${appserver.base}/conf/archiva.xml" 144 */ 145 private String altConfigFilename = "${appserver.base}/conf/archiva.xml"; 146 147 /** 148 * Configuration Listeners we've registered. 149 */ 150 private Set<ConfigurationListener> listeners = new HashSet<ConfigurationListener>(); 151 152 /** 153 * Registry Listeners we've registered. 154 */ 155 private Set<RegistryListener> registryListeners = new HashSet<RegistryListener>(); 156 157 /** 158 * Boolean to help determine if the configuration exists as a result of pulling in 159 * the default-archiva.xml 160 */ 161 private boolean isConfigurationDefaulted = false; 162 163 private static final String KEY = "org.apache.archiva"; 164 165 public Configuration getConfiguration() 166 { 167 return loadConfiguration(); 168 } 169 170 private synchronized Configuration loadConfiguration() 171 { 172 if ( configuration == null ) 173 { 174 configuration = load(); 175 configuration = unescapeExpressions( configuration ); 176 if ( isConfigurationDefaulted ) 177 { 178 configuration = checkRepositoryLocations( configuration ); 179 } 180 } 181 182 return configuration; 183 } 184 185 @SuppressWarnings ( "unchecked" ) 186 private Configuration load() 187 { 188 // TODO: should this be the same as section? make sure unnamed sections still work (eg, sys properties) 189 Registry subset = registry.getSubset( KEY ); 190 if ( subset.getString( "version" ) == null ) 191 { 192 // a little autodetection of v1, even if version is omitted (this was previously allowed) 193 if ( subset.getSubset( "repositoryScanning" ).isEmpty() ) 194 { 195 // only for empty, or v < 1 196 subset = readDefaultConfiguration(); 197 } 198 } 199 200 Configuration config = new ConfigurationRegistryReader().read( subset ); 201 202 config.getRepositoryGroups(); 203 config.getRepositoryGroupsAsMap(); 204 if ( !config.getRepositories().isEmpty() ) 205 { 206 for ( Iterator<V1RepositoryConfiguration> i = config.getRepositories().iterator(); i.hasNext(); ) 207 { 208 V1RepositoryConfiguration r = i.next(); 209 r.setScanned( r.isIndexed() ); 210 211 if ( StringUtils.startsWith( r.getUrl(), "file://" ) ) 212 { 213 r.setLocation( r.getUrl().substring( 7 ) ); 214 config.addManagedRepository( r ); 215 } 216 else if ( StringUtils.startsWith( r.getUrl(), "file:" ) ) 217 { 218 r.setLocation( r.getUrl().substring( 5 ) ); 219 config.addManagedRepository( r ); 220 } 221 else if ( StringUtils.isEmpty( r.getUrl() ) ) 222 { 223 // in case of empty url we can consider it as a managed one 224 // check if location is null 225 //file://${appserver.base}/repositories/${id} 226 if ( StringUtils.isEmpty( r.getLocation() ) ) 227 { 228 r.setLocation( "file://${appserver.base}/repositories/" + r.getId() ); 229 } 230 config.addManagedRepository( r ); 231 } 232 else 233 { 234 RemoteRepositoryConfiguration repo = new RemoteRepositoryConfiguration(); 235 repo.setId( r.getId() ); 236 repo.setLayout( r.getLayout() ); 237 repo.setName( r.getName() ); 238 repo.setUrl( r.getUrl() ); 239 config.addRemoteRepository( repo ); 240 } 241 } 242 243 // Prevent duplicate repositories from showing up. 244 config.getRepositories().clear(); 245 246 registry.removeSubset( KEY + ".repositories" ); 247 } 248 249 if ( !CollectionUtils.isEmpty( config.getRemoteRepositories() ) ) 250 { 251 List<RemoteRepositoryConfiguration> remoteRepos = config.getRemoteRepositories(); 252 for ( RemoteRepositoryConfiguration repo : remoteRepos ) 253 { 254 // [MRM-582] Remote Repositories with empty <username> and <password> fields shouldn't be created in configuration. 255 if ( StringUtils.isBlank( repo.getUsername() ) ) 256 { 257 repo.setUsername( null ); 258 } 259 260 if ( StringUtils.isBlank( repo.getPassword() ) ) 261 { 262 repo.setPassword( null ); 263 } 264 } 265 } 266 267 if ( !config.getProxyConnectors().isEmpty() ) 268 { 269 // Fix Proxy Connector Settings. 270 271 // Create a copy of the list to read from (to prevent concurrent modification exceptions) 272 List<ProxyConnectorConfiguration> proxyConnectorList = 273 new ArrayList<ProxyConnectorConfiguration>( config.getProxyConnectors() ); 274 // Remove the old connector list. 275 config.getProxyConnectors().clear(); 276 277 for ( ProxyConnectorConfiguration connector : proxyConnectorList ) 278 { 279 // Fix policies 280 boolean connectorValid = true; 281 282 Map<String, String> policies = new HashMap<String, String>(); 283 // Make copy of policies 284 policies.putAll( connector.getPolicies() ); 285 // Clear out policies 286 connector.getPolicies().clear(); 287 288 // Work thru policies. cleaning them up. 289 for ( Entry<String, String> entry : policies.entrySet() ) 290 { 291 String policyId = entry.getKey(); 292 String setting = entry.getValue(); 293 294 // Upgrade old policy settings. 295 if ( "releases".equals( policyId ) || "snapshots".equals( policyId ) ) 296 { 297 if ( "ignored".equals( setting ) ) 298 { 299 setting = AbstractUpdatePolicy.ALWAYS; 300 } 301 else if ( "disabled".equals( setting ) ) 302 { 303 setting = AbstractUpdatePolicy.NEVER; 304 } 305 } 306 else if ( "cache-failures".equals( policyId ) ) 307 { 308 if ( "ignored".equals( setting ) ) 309 { 310 setting = CachedFailuresPolicy.NO; 311 } 312 else if ( "cached".equals( setting ) ) 313 { 314 setting = CachedFailuresPolicy.YES; 315 } 316 } 317 else if ( "checksum".equals( policyId ) ) 318 { 319 if ( "ignored".equals( setting ) ) 320 { 321 setting = ChecksumPolicy.IGNORE; 322 } 323 } 324 325 // Validate existance of policy key. 326 if ( policyExists( policyId ) ) 327 { 328 Policy policy = findPolicy( policyId ); 329 // Does option exist? 330 if ( !policy.getOptions().contains( setting ) ) 331 { 332 setting = policy.getDefaultOption(); 333 } 334 connector.addPolicy( policyId, setting ); 335 } 336 else 337 { 338 // Policy key doesn't exist. Don't add it to golden version. 339 log.warn( "Policy [" + policyId + "] does not exist." ); 340 } 341 } 342 343 if ( connectorValid ) 344 { 345 config.addProxyConnector( connector ); 346 } 347 } 348 349 // Normalize the order fields in the proxy connectors. 350 Map<String, java.util.List<ProxyConnectorConfiguration>> proxyConnectorMap = 351 config.getProxyConnectorAsMap(); 352 353 for ( List<ProxyConnectorConfiguration> connectors : proxyConnectorMap.values() ) 354 { 355 // Sort connectors by order field. 356 Collections.sort( connectors, ProxyConnectorConfigurationOrderComparator.getInstance() ); 357 358 // Normalize the order field values. 359 int order = 1; 360 for ( ProxyConnectorConfiguration connector : connectors ) 361 { 362 connector.setOrder( order++ ); 363 } 364 } 365 } 366 367 return config; 368 } 369 370 private Policy findPolicy( String policyId ) 371 { 372 if ( MapUtils.isEmpty( prePolicies ) ) 373 { 374 log.error( "No PreDownloadPolicies found!" ); 375 return null; 376 } 377 378 if ( MapUtils.isEmpty( postPolicies ) ) 379 { 380 log.error( "No PostDownloadPolicies found!" ); 381 return null; 382 } 383 384 Policy policy; 385 386 policy = prePolicies.get( policyId ); 387 if ( policy != null ) 388 { 389 return policy; 390 } 391 392 policy = postPolicies.get( policyId ); 393 if ( policy != null ) 394 { 395 return policy; 396 } 397 398 policy = downloadErrorPolicies.get( policyId ); 399 if ( policy != null ) 400 { 401 return policy; 402 } 403 404 return null; 405 } 406 407 private boolean policyExists( String policyId ) 408 { 409 if ( MapUtils.isEmpty( prePolicies ) ) 410 { 411 log.error( "No PreDownloadPolicies found!" ); 412 return false; 413 } 414 415 if ( MapUtils.isEmpty( postPolicies ) ) 416 { 417 log.error( "No PostDownloadPolicies found!" ); 418 return false; 419 } 420 421 return ( prePolicies.containsKey( policyId ) || postPolicies.containsKey( policyId ) 422 || downloadErrorPolicies.containsKey( policyId ) ); 423 } 424 425 private Registry readDefaultConfiguration() 426 { 427 // if it contains some old configuration, remove it (Archiva 0.9) 428 registry.removeSubset( KEY ); 429 430 try 431 { 432 registry.addConfigurationFromResource( "org/apache/archiva/configuration/default-archiva.xml", KEY ); 433 this.isConfigurationDefaulted = true; 434 } 435 catch ( RegistryException e ) 436 { 437 throw new ConfigurationRuntimeException( 438 "Fatal error: Unable to find the built-in default configuration and load it into the registry", e ); 439 } 440 return registry.getSubset( KEY ); 441 } 442 443 @SuppressWarnings ( "unchecked" ) 444 public synchronized void save( Configuration configuration ) 445 throws IndeterminateConfigurationException, RegistryException 446 { 447 Registry section = registry.getSection( KEY + ".user" ); 448 Registry baseSection = registry.getSection( KEY + ".base" ); 449 if ( section == null ) 450 { 451 section = baseSection; 452 if ( section == null ) 453 { 454 section = createDefaultConfigurationFile(); 455 } 456 } 457 else if ( baseSection != null ) 458 { 459 Collection<String> keys = baseSection.getKeys(); 460 boolean foundList = false; 461 for ( Iterator<String> i = keys.iterator(); i.hasNext() && !foundList; ) 462 { 463 String key = i.next(); 464 465 // a little aggressive with the repositoryScanning and databaseScanning - should be no need to split 466 // that configuration 467 if ( key.startsWith( "repositories" ) || key.startsWith( "proxyConnectors" ) || key.startsWith( 468 "networkProxies" ) || key.startsWith( "repositoryScanning" ) || key.startsWith( 469 "remoteRepositories" ) || key.startsWith( "managedRepositories" ) || key.startsWith( 470 "repositoryGroups" ) ) 471 { 472 foundList = true; 473 } 474 } 475 476 if ( foundList ) 477 { 478 this.configuration = null; 479 480 throw new IndeterminateConfigurationException( 481 "Configuration can not be saved when it is loaded from two sources" ); 482 } 483 } 484 485 // escape all cron expressions to handle ',' 486 escapeCronExpressions( configuration ); 487 488 // [MRM-661] Due to a bug in the modello registry writer, we need to take these out by hand. They'll be put back by the writer. 489 if ( configuration.getManagedRepositories().isEmpty() && section != null ) 490 { 491 section.removeSubset( "managedRepositories" ); 492 } 493 if ( configuration.getRemoteRepositories().isEmpty() && section != null ) 494 { 495 section.removeSubset( "remoteRepositories" ); 496 497 } 498 if ( configuration.getProxyConnectors().isEmpty() && section != null ) 499 { 500 section.removeSubset( "proxyConnectors" ); 501 } 502 if ( configuration.getNetworkProxies().isEmpty() && section != null ) 503 { 504 section.removeSubset( "networkProxies" ); 505 } 506 if ( configuration.getLegacyArtifactPaths().isEmpty() && section != null ) 507 { 508 section.removeSubset( "legacyArtifactPaths" ); 509 } 510 if ( configuration.getRepositoryGroups().isEmpty() && section != null ) 511 { 512 section.removeSubset( "repositoryGroups" ); 513 } 514 if ( configuration.getRepositoryScanning() != null ) 515 { 516 if ( configuration.getRepositoryScanning().getKnownContentConsumers().isEmpty() && section != null ) 517 { 518 section.removeSubset( "repositoryScanning.knownContentConsumers" ); 519 } 520 if ( configuration.getRepositoryScanning().getInvalidContentConsumers().isEmpty() && section != null ) 521 { 522 section.removeSubset( "repositoryScanning.invalidContentConsumers" ); 523 } 524 } 525 526 new ConfigurationRegistryWriter().write( configuration, section ); 527 section.save(); 528 529 this.configuration = unescapeExpressions( configuration ); 530 531 triggerEvent( ConfigurationEvent.SAVED ); 532 } 533 534 private void escapeCronExpressions( Configuration configuration ) 535 { 536 for ( ManagedRepositoryConfiguration c : configuration.getManagedRepositories() ) 537 { 538 c.setRefreshCronExpression( escapeCronExpression( c.getRefreshCronExpression() ) ); 539 } 540 541 542 } 543 544 private Registry createDefaultConfigurationFile() 545 throws RegistryException 546 { 547 // TODO: may not be needed under commons-configuration 1.4 - check 548 549 String contents = "<configuration />"; 550 551 String fileLocation = userConfigFilename; 552 553 if ( !writeFile( "user configuration", userConfigFilename, contents ) ) 554 { 555 fileLocation = altConfigFilename; 556 if ( !writeFile( "alternative configuration", altConfigFilename, contents ) ) 557 { 558 throw new RegistryException( 559 "Unable to create configuration file in either user [" + userConfigFilename + "] or alternative [" 560 + altConfigFilename 561 + "] locations on disk, usually happens when not allowed to write to those locations." ); 562 } 563 } 564 565 // olamy hackish I know :-) 566 contents = "<configuration><xml fileName=\"" + fileLocation 567 + "\" config-forceCreate=\"true\" config-name=\"org.apache.archiva.user\"/>" + "</configuration>"; 568 569 ( (CommonsConfigurationRegistry) registry ).setProperties( contents ); 570 571 registry.initialize(); 572 573 for ( RegistryListener regListener : registryListeners ) 574 { 575 addRegistryChangeListener( regListener ); 576 } 577 578 triggerEvent( ConfigurationEvent.SAVED ); 579 580 Registry section = registry.getSection( KEY + ".user" ); 581 return section == null ? new CommonsConfigurationRegistry( new BaseConfiguration() ) : section; 582 } 583 584 /** 585 * Attempts to write the contents to a file, if an IOException occurs, return false. 586 * <p/> 587 * The file will be created if the directory to the file exists, otherwise this will return false. 588 * 589 * @param filetype the filetype (freeform text) to use in logging messages when failure to write. 590 * @param path the path to write to. 591 * @param contents the contents to write. 592 * @return true if write successful. 593 */ 594 private boolean writeFile( String filetype, String path, String contents ) 595 { 596 File file = new File( path ); 597 598 try 599 { 600 // Check parent directory (if it is declared) 601 if ( file.getParentFile() != null ) 602 { 603 // Check that directory exists 604 if ( ! file.getParentFile().isDirectory() ) 605 { 606 // Directory to file must exist for file to be created 607 return false; 608 } 609 } 610 611 FileUtils.writeStringToFile( file, contents, "UTF-8" ); 612 return true; 613 } 614 catch ( IOException e ) 615 { 616 log.error( "Unable to create " + filetype + " file: " + e.getMessage(), e ); 617 return false; 618 } 619 } 620 621 private void triggerEvent( int type ) 622 { 623 ConfigurationEvent evt = new ConfigurationEvent( type ); 624 for ( ConfigurationListener listener : listeners ) 625 { 626 listener.configurationEvent( evt ); 627 } 628 } 629 630 public void addListener( ConfigurationListener listener ) 631 { 632 if ( listener == null ) 633 { 634 return; 635 } 636 637 listeners.add( listener ); 638 } 639 640 public void removeListener( ConfigurationListener listener ) 641 { 642 if ( listener == null ) 643 { 644 return; 645 } 646 647 listeners.remove( listener ); 648 } 649 650 public void addChangeListener( RegistryListener listener ) 651 { 652 addRegistryChangeListener( listener ); 653 654 // keep track for later 655 registryListeners.add( listener ); 656 } 657 658 private void addRegistryChangeListener( RegistryListener listener ) 659 { 660 Registry section = registry.getSection( KEY + ".user" ); 661 if ( section != null ) 662 { 663 section.addChangeListener( listener ); 664 } 665 section = registry.getSection( KEY + ".base" ); 666 if ( section != null ) 667 { 668 section.addChangeListener( listener ); 669 } 670 } 671 672 @PostConstruct 673 public void initialize() 674 { 675 676 this.postPolicies = componentContainer.buildMapWithRole( PostDownloadPolicy.class ); 677 this.prePolicies = componentContainer.buildMapWithRole( PreDownloadPolicy.class ); 678 this.downloadErrorPolicies = componentContainer.buildMapWithRole( DownloadErrorPolicy.class ); 679 // Resolve expressions in the userConfigFilename and altConfigFilename 680 try 681 { 682 ExpressionEvaluator expressionEvaluator = new DefaultExpressionEvaluator(); 683 expressionEvaluator.addExpressionSource( new SystemPropertyExpressionSource() ); 684 String userConfigFileNameSysProps = System.getProperty( "archiva.user.configFileName" ); 685 if ( StringUtils.isNotBlank( userConfigFileNameSysProps ) ) 686 { 687 userConfigFilename = userConfigFileNameSysProps; 688 } 689 else 690 { 691 userConfigFilename = expressionEvaluator.expand( userConfigFilename ); 692 } 693 altConfigFilename = expressionEvaluator.expand( altConfigFilename ); 694 loadConfiguration(); 695 handleUpgradeConfiguration(); 696 } 697 catch ( IndeterminateConfigurationException e ) 698 { 699 throw new RuntimeException( "failed during upgrade from previous version" + e.getMessage(), e ); 700 } 701 catch ( RegistryException e ) 702 { 703 throw new RuntimeException( "failed during upgrade from previous version" + e.getMessage(), e ); 704 } 705 catch ( EvaluatorException e ) 706 { 707 throw new RuntimeException( 708 "Unable to evaluate expressions found in " + "userConfigFilename or altConfigFilename.", e); 709 } 710 registry.addChangeListener( this ); 711 } 712 713 /** 714 * upgrade from 1.3 715 */ 716 private void handleUpgradeConfiguration() 717 throws RegistryException, IndeterminateConfigurationException 718 { 719 720 List<String> dbConsumers = Arrays.asList( "update-db-artifact", "update-db-repository-metadata" ); 721 722 // remove database consumers if here 723 List<String> intersec = 724 ListUtils.intersection( dbConsumers, configuration.getRepositoryScanning().getKnownContentConsumers() ); 725 726 if ( !intersec.isEmpty() ) 727 { 728 729 List<String> knowContentConsumers = 730 new ArrayList<String>( configuration.getRepositoryScanning().getKnownContentConsumers().size() ); 731 for ( String knowContentConsumer : configuration.getRepositoryScanning().getKnownContentConsumers() ) 732 { 733 if ( !dbConsumers.contains( knowContentConsumer ) ) 734 { 735 knowContentConsumers.add( knowContentConsumer ); 736 } 737 } 738 739 configuration.getRepositoryScanning().setKnownContentConsumers( knowContentConsumers ); 740 } 741 742 // ensure create-archiva-metadata is here 743 if ( !configuration.getRepositoryScanning().getKnownContentConsumers().contains( "create-archiva-metadata" ) ) 744 { 745 List<String> knowContentConsumers = 746 new ArrayList<String>( configuration.getRepositoryScanning().getKnownContentConsumers() ); 747 knowContentConsumers.add( "create-archiva-metadata" ); 748 configuration.getRepositoryScanning().setKnownContentConsumers( knowContentConsumers ); 749 } 750 751 // ensure duplicate-artifacts is here 752 if ( !configuration.getRepositoryScanning().getKnownContentConsumers().contains( "duplicate-artifacts" ) ) 753 { 754 List<String> knowContentConsumers = 755 new ArrayList<String>( configuration.getRepositoryScanning().getKnownContentConsumers() ); 756 knowContentConsumers.add( "duplicate-artifacts" ); 757 configuration.getRepositoryScanning().setKnownContentConsumers( knowContentConsumers ); 758 } 759 // save ?? 760 //save( configuration ); 761 } 762 763 public void reload() 764 { 765 this.configuration = null; 766 try 767 { 768 this.registry.initialize(); 769 } 770 catch ( RegistryException e ) 771 { 772 throw new ConfigurationRuntimeException( e.getMessage(), e ); 773 } 774 this.initialize(); 775 } 776 777 public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue ) 778 { 779 // nothing to do here 780 } 781 782 public synchronized void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) 783 { 784 configuration = null; 785 } 786 787 private String removeExpressions( String directory ) 788 { 789 String value = StringUtils.replace( directory, "${appserver.base}", 790 registry.getString( "appserver.base", "${appserver.base}" ) ); 791 value = StringUtils.replace( value, "${appserver.home}", 792 registry.getString( "appserver.home", "${appserver.home}" ) ); 793 return value; 794 } 795 796 private String unescapeCronExpression( String cronExpression ) 797 { 798 return StringUtils.replace( cronExpression, "\\,", "," ); 799 } 800 801 private String escapeCronExpression( String cronExpression ) 802 { 803 return StringUtils.replace( cronExpression, ",", "\\," ); 804 } 805 806 private Configuration unescapeExpressions( Configuration config ) 807 { 808 // TODO: for commons-configuration 1.3 only 809 for ( Iterator<ManagedRepositoryConfiguration> i = config.getManagedRepositories().iterator(); i.hasNext(); ) 810 { 811 ManagedRepositoryConfiguration c = i.next(); 812 c.setLocation( removeExpressions( c.getLocation() ) ); 813 c.setRefreshCronExpression( unescapeCronExpression( c.getRefreshCronExpression() ) ); 814 } 815 816 return config; 817 } 818 819 private Configuration checkRepositoryLocations( Configuration config ) 820 { 821 // additional check for [MRM-789], ensure that the location of the default repositories 822 // are not installed in the server installation 823 for ( ManagedRepositoryConfiguration repo : (List<ManagedRepositoryConfiguration>) config.getManagedRepositories() ) 824 { 825 String repoPath = repo.getLocation(); 826 File repoLocation = new File( repoPath ); 827 828 if ( repoLocation.exists() && repoLocation.isDirectory() && !repoPath.endsWith( 829 "data/repositories/" + repo.getId() ) ) 830 { 831 repo.setLocation( repoPath + "/data/repositories/" + repo.getId() ); 832 } 833 } 834 835 return config; 836 } 837 838 public String getUserConfigFilename() 839 { 840 return userConfigFilename; 841 } 842 843 public String getAltConfigFilename() 844 { 845 return altConfigFilename; 846 } 847 848 public boolean isDefaulted() 849 { 850 return this.isConfigurationDefaulted; 851 } 852 853 public Registry getRegistry() 854 { 855 return registry; 856 } 857 858 public void setRegistry( Registry registry ) 859 { 860 this.registry = registry; 861 } 862 863 864 public void setUserConfigFilename( String userConfigFilename ) 865 { 866 this.userConfigFilename = userConfigFilename; 867 } 868 869 public void setAltConfigFilename( String altConfigFilename ) 870 { 871 this.altConfigFilename = altConfigFilename; 872 } 873 }