1 package org.apache.archiva.configuration;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.configuration.functors.ProxyConnectorConfigurationOrderComparator;
23 import org.apache.archiva.configuration.io.registry.ConfigurationRegistryReader;
24 import org.apache.archiva.configuration.io.registry.ConfigurationRegistryWriter;
25 import org.apache.archiva.policies.AbstractUpdatePolicy;
26 import org.apache.archiva.policies.CachedFailuresPolicy;
27 import org.apache.archiva.policies.ChecksumPolicy;
28 import org.apache.archiva.policies.DownloadErrorPolicy;
29 import org.apache.archiva.policies.Policy;
30 import org.apache.archiva.policies.PostDownloadPolicy;
31 import org.apache.archiva.policies.PreDownloadPolicy;
32 import org.apache.archiva.redback.components.evaluator.DefaultExpressionEvaluator;
33 import org.apache.archiva.redback.components.evaluator.EvaluatorException;
34 import org.apache.archiva.redback.components.evaluator.ExpressionEvaluator;
35 import org.apache.archiva.redback.components.evaluator.sources.SystemPropertyExpressionSource;
36 import org.apache.archiva.redback.components.registry.Registry;
37 import org.apache.archiva.redback.components.registry.RegistryException;
38 import org.apache.archiva.redback.components.registry.RegistryListener;
39 import org.apache.archiva.redback.components.registry.commons.CommonsConfigurationRegistry;
40 import org.apache.archiva.redback.components.springutils.ComponentContainer;
41 import org.apache.commons.collections.CollectionUtils;
42 import org.apache.commons.collections.ListUtils;
43 import org.apache.commons.collections.MapUtils;
44 import org.apache.commons.configuration.BaseConfiguration;
45 import org.apache.commons.io.FileUtils;
46 import org.apache.commons.lang.StringUtils;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.springframework.stereotype.Service;
51 import javax.annotation.PostConstruct;
52 import javax.inject.Inject;
53 import javax.inject.Named;
54 import java.io.IOException;
55 import java.nio.file.Files;
56 import java.nio.file.Path;
57 import java.nio.file.Paths;
58 import java.util.ArrayList;
59 import java.util.Arrays;
60 import java.util.Collection;
61 import java.util.Collections;
62 import java.util.HashMap;
63 import java.util.HashSet;
64 import java.util.Iterator;
65 import java.util.List;
66 import java.util.Locale;
68 import java.util.Map.Entry;
73 * Implementation of configuration holder that retrieves it from the registry.
76 * The registry layers and merges the 2 configuration files: user, and application server.
79 * Instead of relying on the model defaults, if the registry is empty a default configuration file is loaded and
80 * applied from a resource. The defaults are not loaded into the registry as the lists (eg repositories) could no longer
81 * be removed if that was the case.
84 * When saving the configuration, it is saved to the location it was read from. If it was read from the defaults, it
85 * will be saved to the user location.
86 * However, if the configuration contains information from both sources, an exception is raised as this is currently
87 * unsupported. The reason for this is that it is not possible to identify where to re-save elements, and can result
88 * in list configurations (eg repositories) becoming inconsistent.
91 * If the configuration is outdated, it will be upgraded when it is loaded. This is done by checking the version flag
92 * before reading it from the registry.
94 * FIXME: The synchronization must be improved, the current impl may lead to inconsistent data or multiple getConfiguration() calls (martin_s@apache.org)
97 @Service("archivaConfiguration#default")
98 public class DefaultArchivaConfiguration
99 implements ArchivaConfiguration, RegistryListener
101 private Logger log = LoggerFactory.getLogger( DefaultArchivaConfiguration.class );
103 private static String FILE_ENCODING = "UTF-8";
106 * Plexus registry to read the configuration from.
109 @Named(value = "commons-configuration")
110 private Registry registry;
113 private ComponentContainer componentContainer;
116 * The configuration that has been converted.
118 private Configuration configuration;
123 * @todo these don't strictly belong in here
125 private Map<String, PreDownloadPolicy> prePolicies;
130 * @todo these don't strictly belong in here
132 private Map<String, PostDownloadPolicy> postPolicies;
137 * @todo these don't strictly belong in here
139 private Map<String, DownloadErrorPolicy> downloadErrorPolicies;
144 * default-value="${user.home}/.m2/archiva.xml"
146 private String userConfigFilename = "${user.home}/.m2/archiva.xml";
150 * default-value="${appserver.base}/conf/archiva.xml"
152 private String altConfigFilename = "${appserver.base}/conf/archiva.xml";
155 * Configuration Listeners we've registered.
157 private Set<ConfigurationListener> listeners = new HashSet<>();
160 * Registry Listeners we've registered.
162 private Set<RegistryListener> registryListeners = new HashSet<>();
165 * Boolean to help determine if the configuration exists as a result of pulling in
166 * the default-archiva.xml
168 private boolean isConfigurationDefaulted = false;
170 private static final String KEY = "org.apache.archiva";
172 // Section used for default only configuration
173 private static final String KEY_DEFAULT_ONLY = "org.apache.archiva_default";
175 private Locale defaultLocale = Locale.getDefault();
177 private List<Locale.LanguageRange> languagePriorities = new ArrayList<>( );
179 private volatile Path dataDirectory;
180 private volatile Path repositoryBaseDirectory;
181 private volatile Path remoteRepositoryBaseDirectory;
184 private void init() {
185 languagePriorities = Locale.LanguageRange.parse( "en,fr,de" );
191 public Configuration getConfiguration()
193 return loadConfiguration();
196 private synchronized Configuration loadConfiguration()
198 if ( configuration == null )
200 configuration = load();
201 configuration = unescapeExpressions( configuration );
202 if ( isConfigurationDefaulted )
204 configuration = checkRepositoryLocations( configuration );
208 return configuration;
211 private boolean hasConfigVersionChanged(Configuration current, Registry defaultOnlyConfiguration) {
212 return current==null || current.getVersion()==null ||
213 !current.getVersion().trim().equals(defaultOnlyConfiguration.getString("version","").trim());
216 @SuppressWarnings("unchecked")
217 private Configuration load()
219 // TODO: should this be the same as section? make sure unnamed sections still work (eg, sys properties)
220 Registry subset = registry.getSubset( KEY );
221 if ( subset.getString( "version" ) == null )
223 if ( subset.getSubset( "repositoryScanning" ).isEmpty() )
226 subset = readDefaultConfiguration();
229 throw new RuntimeException( "No version tag found in configuration. Archiva configuration version 1.x is not longer supported." );
233 Configuration config = new ConfigurationRegistryReader().read( subset );
235 // Resolving data and repositories directories
236 // If the config entries are absolute, the path is used as it is
237 // if the config entries are empty, they are resolved:
238 // dataDirectory = ${appserver.base}/data
239 // repositoryDirectory = ${dataDirectory}/repositories
240 // If the entries are relative they are resolved
241 // relative to the appserver.base, for dataDirectory
242 // relative to dataDirectory for repositoryBase
243 String dataDir = config.getArchivaRuntimeConfiguration().getDataDirectory();
244 if (StringUtils.isEmpty( dataDir )) {
245 dataDirectory = getAppServerBaseDir().resolve( "data");
247 Path tmpDataDir = Paths.get(dataDir);
248 if (tmpDataDir.isAbsolute()) {
249 dataDirectory = tmpDataDir;
251 dataDirectory = getAppServerBaseDir().resolve(tmpDataDir);
254 config.getArchivaRuntimeConfiguration().setDataDirectory( dataDirectory.normalize().toString() );
255 String repoBaseDir = config.getArchivaRuntimeConfiguration().getRepositoryBaseDirectory();
256 if (StringUtils.isEmpty( repoBaseDir )) {
257 repositoryBaseDirectory = dataDirectory.resolve("repositories");
260 Path tmpRepoBaseDir = Paths.get(repoBaseDir);
261 if (tmpRepoBaseDir.isAbsolute()) {
262 repositoryBaseDirectory = tmpRepoBaseDir;
264 dataDirectory.resolve(tmpRepoBaseDir);
267 String remoteRepoBaseDir = config.getArchivaRuntimeConfiguration().getRemoteRepositoryBaseDirectory();
268 if (StringUtils.isEmpty(remoteRepoBaseDir)) {
269 remoteRepositoryBaseDirectory = dataDirectory.resolve("remotes");
271 Path tmpRemoteRepoDir = Paths.get(remoteRepoBaseDir);
272 if (tmpRemoteRepoDir.isAbsolute()) {
273 remoteRepositoryBaseDirectory = tmpRemoteRepoDir;
275 dataDirectory.resolve(tmpRemoteRepoDir);
280 config.getRepositoryGroups();
281 config.getRepositoryGroupsAsMap();
282 if ( !CollectionUtils.isEmpty( config.getRemoteRepositories() ) )
284 List<RemoteRepositoryConfiguration> remoteRepos = config.getRemoteRepositories();
285 for ( RemoteRepositoryConfiguration repo : remoteRepos )
287 // [MRM-582] Remote Repositories with empty <username> and <password> fields shouldn't be created in configuration.
288 if ( StringUtils.isBlank( repo.getUsername() ) )
290 repo.setUsername( null );
293 if ( StringUtils.isBlank( repo.getPassword() ) )
295 repo.setPassword( null );
300 if ( !config.getProxyConnectors().isEmpty() )
302 // Fix Proxy Connector Settings.
304 // Create a copy of the list to read from (to prevent concurrent modification exceptions)
305 List<ProxyConnectorConfiguration> proxyConnectorList = new ArrayList<>( config.getProxyConnectors() );
306 // Remove the old connector list.
307 config.getProxyConnectors().clear();
309 for ( ProxyConnectorConfiguration connector : proxyConnectorList )
312 boolean connectorValid = true;
314 Map<String, String> policies = new HashMap<>();
315 // Make copy of policies
316 policies.putAll( connector.getPolicies() );
317 // Clear out policies
318 connector.getPolicies().clear();
320 // Work thru policies. cleaning them up.
321 for ( Entry<String, String> entry : policies.entrySet() )
323 String policyId = entry.getKey();
324 String setting = entry.getValue();
326 // Upgrade old policy settings.
327 if ( "releases".equals( policyId ) || "snapshots".equals( policyId ) )
329 if ( "ignored".equals( setting ) )
331 setting = AbstractUpdatePolicy.ALWAYS;
333 else if ( "disabled".equals( setting ) )
335 setting = AbstractUpdatePolicy.NEVER;
338 else if ( "cache-failures".equals( policyId ) )
340 if ( "ignored".equals( setting ) )
342 setting = CachedFailuresPolicy.NO;
344 else if ( "cached".equals( setting ) )
346 setting = CachedFailuresPolicy.YES;
349 else if ( "checksum".equals( policyId ) )
351 if ( "ignored".equals( setting ) )
353 setting = ChecksumPolicy.IGNORE;
357 // Validate existance of policy key.
358 if ( policyExists( policyId ) )
360 Policy policy = findPolicy( policyId );
361 // Does option exist?
362 if ( !policy.getOptions().contains( setting ) )
364 setting = policy.getDefaultOption();
366 connector.addPolicy( policyId, setting );
370 // Policy key doesn't exist. Don't add it to golden version.
371 log.warn( "Policy [{}] does not exist.", policyId );
375 if ( connectorValid )
377 config.addProxyConnector( connector );
381 // Normalize the order fields in the proxy connectors.
382 Map<String, java.util.List<ProxyConnectorConfiguration>> proxyConnectorMap =
383 config.getProxyConnectorAsMap();
385 for ( List<ProxyConnectorConfiguration> connectors : proxyConnectorMap.values() )
387 // Sort connectors by order field.
388 Collections.sort( connectors, ProxyConnectorConfigurationOrderComparator.getInstance() );
390 // Normalize the order field values.
392 for ( ProxyConnectorConfiguration connector : connectors )
394 connector.setOrder( order++ );
399 this.defaultLocale = Locale.forLanguageTag( config.getArchivaRuntimeConfiguration().getDefaultLanguage() );
400 this.languagePriorities = Locale.LanguageRange.parse(config.getArchivaRuntimeConfiguration().getLanguageRange());
405 * Updates the checkpath list for repositories.
407 * We are replacing existing ones and adding new ones. This allows to update the list with new releases.
409 * We are also updating existing remote repositories, if they exist already.
411 * This update method should only be called, if the config version changes to avoid overwriting
412 * user repository settings all the time.
414 private void updateCheckPathDefaults(Configuration config, Registry defaultConfiguration) {
415 List<RepositoryCheckPath> existingCheckPathList = config.getArchivaDefaultConfiguration().getDefaultCheckPaths();
416 HashMap<String, RepositoryCheckPath> existingCheckPaths = new HashMap<>();
417 HashMap<String, RepositoryCheckPath> newCheckPaths = new HashMap<>();
418 for (RepositoryCheckPath path : config.getArchivaDefaultConfiguration().getDefaultCheckPaths()) {
419 existingCheckPaths.put(path.getUrl(), path);
421 List defaultCheckPathsSubsets = defaultConfiguration.getSubsetList("archivaDefaultConfiguration.defaultCheckPaths.defaultCheckPath" );
422 for ( Iterator i = defaultCheckPathsSubsets.iterator(); i.hasNext(); )
424 RepositoryCheckPath v = readRepositoryCheckPath( (Registry) i.next() );
425 if (existingCheckPaths.containsKey(v.getUrl())) {
426 existingCheckPathList.remove(existingCheckPaths.get(v.getUrl()));
428 existingCheckPathList.add(v);
429 newCheckPaths.put(v.getUrl(), v);
431 // Remote repositories update
432 for (RemoteRepositoryConfiguration remoteRepositoryConfiguration : config.getRemoteRepositories()) {
433 String url = remoteRepositoryConfiguration.getUrl().toLowerCase();
434 if (newCheckPaths.containsKey(url)) {
435 String currentPath = remoteRepositoryConfiguration.getCheckPath();
436 String newPath = newCheckPaths.get(url).getPath();
437 log.info("Updating connection check path for repository {}, from '{}' to '{}'.", remoteRepositoryConfiguration.getId(),
438 currentPath, newPath);
439 remoteRepositoryConfiguration.setCheckPath(newPath);
444 private RepositoryCheckPath readRepositoryCheckPath( Registry registry )
446 RepositoryCheckPath value = new RepositoryCheckPath();
448 String url = registry.getString( "url", value.getUrl() );
451 String path = registry.getString( "path", value.getPath() );
452 value.setPath( path );
456 private Policy findPolicy( String policyId )
458 if ( MapUtils.isEmpty( prePolicies ) )
460 log.error( "No PreDownloadPolicies found!" );
464 if ( MapUtils.isEmpty( postPolicies ) )
466 log.error( "No PostDownloadPolicies found!" );
472 policy = prePolicies.get( policyId );
473 if ( policy != null )
478 policy = postPolicies.get( policyId );
479 if ( policy != null )
484 policy = downloadErrorPolicies.get( policyId );
485 if ( policy != null )
493 private boolean policyExists( String policyId )
495 if ( MapUtils.isEmpty( prePolicies ) )
497 log.error( "No PreDownloadPolicies found!" );
501 if ( MapUtils.isEmpty( postPolicies ) )
503 log.error( "No PostDownloadPolicies found!" );
507 return ( prePolicies.containsKey( policyId ) || postPolicies.containsKey( policyId )
508 || downloadErrorPolicies.containsKey( policyId ) );
511 private Registry readDefaultConfiguration()
513 // if it contains some old configuration, remove it (Archiva 0.9)
514 registry.removeSubset( KEY );
518 registry.addConfigurationFromResource( "org/apache/archiva/configuration/default-archiva.xml", KEY );
519 this.isConfigurationDefaulted = true;
521 catch ( RegistryException e )
523 throw new ConfigurationRuntimeException(
524 "Fatal error: Unable to find the built-in default configuration and load it into the registry", e );
526 return registry.getSubset( KEY );
530 * Reads the default only configuration into a special prefix. This allows to check for changes
531 * of the default configuration.
533 private Registry readDefaultOnlyConfiguration()
535 registry.removeSubset(KEY_DEFAULT_ONLY);
538 registry.addConfigurationFromResource( "org/apache/archiva/configuration/default-archiva.xml", KEY_DEFAULT_ONLY);
540 catch ( RegistryException e )
542 throw new ConfigurationRuntimeException(
543 "Fatal error: Unable to find the built-in default configuration and load it into the registry", e );
545 return registry.getSubset(KEY_DEFAULT_ONLY);
548 @SuppressWarnings("unchecked")
550 public synchronized void save( Configuration configuration )
551 throws IndeterminateConfigurationException, RegistryException
553 Registry section = registry.getSection( KEY + ".user" );
554 Registry baseSection = registry.getSection( KEY + ".base" );
555 if ( section == null )
557 section = baseSection;
558 if ( section == null )
560 section = createDefaultConfigurationFile();
563 else if ( baseSection != null )
565 Collection<String> keys = baseSection.getKeys();
566 boolean foundList = false;
567 for ( Iterator<String> i = keys.iterator(); i.hasNext() && !foundList; )
569 String key = i.next();
571 // a little aggressive with the repositoryScanning and databaseScanning - should be no need to split
572 // that configuration
573 if ( key.startsWith( "repositories" ) //
574 || key.startsWith( "proxyConnectors" ) //
575 || key.startsWith( "networkProxies" ) //
576 || key.startsWith( "repositoryScanning" ) //
577 || key.startsWith( "remoteRepositories" ) //
578 || key.startsWith( "managedRepositories" ) //
579 || key.startsWith( "repositoryGroups" ) ) //
587 this.configuration = null;
589 throw new IndeterminateConfigurationException(
590 "Configuration can not be saved when it is loaded from two sources" );
594 // escape all cron expressions to handle ','
595 escapeCronExpressions( configuration );
597 // [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.
598 if ( section != null )
600 if ( configuration.getManagedRepositories().isEmpty() )
602 section.removeSubset( "managedRepositories" );
604 if ( configuration.getRemoteRepositories().isEmpty() )
606 section.removeSubset( "remoteRepositories" );
609 if ( configuration.getProxyConnectors().isEmpty() )
611 section.removeSubset( "proxyConnectors" );
613 if ( configuration.getNetworkProxies().isEmpty() )
615 section.removeSubset( "networkProxies" );
617 if ( configuration.getLegacyArtifactPaths().isEmpty() )
619 section.removeSubset( "legacyArtifactPaths" );
621 if ( configuration.getRepositoryGroups().isEmpty() )
623 section.removeSubset( "repositoryGroups" );
625 if ( configuration.getRepositoryScanning() != null )
627 if ( configuration.getRepositoryScanning().getKnownContentConsumers().isEmpty() )
629 section.removeSubset( "repositoryScanning.knownContentConsumers" );
631 if ( configuration.getRepositoryScanning().getInvalidContentConsumers().isEmpty() )
633 section.removeSubset( "repositoryScanning.invalidContentConsumers" );
636 if (configuration.getArchivaRuntimeConfiguration()!=null) {
637 section.removeSubset("archivaRuntimeConfiguration.defaultCheckPaths");
640 new ConfigurationRegistryWriter().write( configuration, section );
646 this.configuration = unescapeExpressions( configuration );
647 isConfigurationDefaulted=false;
649 triggerEvent( ConfigurationEvent.SAVED );
652 private void escapeCronExpressions( Configuration configuration )
654 for ( ManagedRepositoryConfiguration c : configuration.getManagedRepositories() )
656 c.setRefreshCronExpression( escapeCronExpression( c.getRefreshCronExpression() ) );
660 private Registry createDefaultConfigurationFile()
661 throws RegistryException
663 // TODO: may not be needed under commons-configuration 1.4 - check
665 String contents = "<configuration />";
667 String fileLocation = userConfigFilename;
669 if ( !writeFile( "user configuration", userConfigFilename, contents ) )
671 fileLocation = altConfigFilename;
672 if ( !writeFile( "alternative configuration", altConfigFilename, contents ) )
674 throw new RegistryException(
675 "Unable to create configuration file in either user [" + userConfigFilename + "] or alternative ["
677 + "] locations on disk, usually happens when not allowed to write to those locations." );
681 // olamy hackish I know :-)
682 contents = "<configuration><xml fileName=\"" + fileLocation
683 + "\" config-forceCreate=\"true\" config-name=\"org.apache.archiva.user\"/>" + "</configuration>";
685 ( (CommonsConfigurationRegistry) registry ).setProperties( contents );
687 registry.initialize();
689 for ( RegistryListener regListener : registryListeners )
691 addRegistryChangeListener( regListener );
694 triggerEvent( ConfigurationEvent.SAVED );
696 Registry section = registry.getSection( KEY + ".user" );
697 return section == null ? new CommonsConfigurationRegistry( new BaseConfiguration() ) : section;
701 * Attempts to write the contents to a file, if an IOException occurs, return false.
703 * The file will be created if the directory to the file exists, otherwise this will return false.
705 * @param filetype the filetype (freeform text) to use in logging messages when failure to write.
706 * @param path the path to write to.
707 * @param contents the contents to write.
708 * @return true if write successful.
710 private boolean writeFile( String filetype, String path, String contents )
712 Path file = Paths.get( path );
716 // Check parent directory (if it is declared)
717 if ( file.getParent() != null )
719 // Check that directory exists
720 if ( !Files.isDirectory( file.getParent() ) )
722 // Directory to file must exist for file to be created
726 FileUtils.writeStringToFile( file.toFile(), contents, FILE_ENCODING);
729 catch ( IOException e )
731 log.error( "Unable to create {} file: {}", filetype, e.getMessage(), e );
736 private void triggerEvent( int type )
738 ConfigurationEvent evt = new ConfigurationEvent( type );
739 for ( ConfigurationListener listener : listeners )
741 listener.configurationEvent( evt );
746 public void addListener( ConfigurationListener listener )
748 if ( listener == null )
753 listeners.add( listener );
757 public void removeListener( ConfigurationListener listener )
759 if ( listener == null )
764 listeners.remove( listener );
769 public void addChangeListener( RegistryListener listener )
771 addRegistryChangeListener( listener );
773 // keep track for later
774 registryListeners.add( listener );
777 private void addRegistryChangeListener( RegistryListener listener )
779 Registry section = registry.getSection( KEY + ".user" );
780 if ( section != null )
782 section.addChangeListener( listener );
784 section = registry.getSection( KEY + ".base" );
785 if ( section != null )
787 section.addChangeListener( listener );
792 public void removeChangeListener( RegistryListener listener )
794 boolean removed = registryListeners.remove( listener );
795 log.debug( "RegistryListener: '{}' removed {}", listener, removed );
797 Registry section = registry.getSection( KEY + ".user" );
798 if ( section != null )
800 section.removeChangeListener( listener );
802 section = registry.getSection( KEY + ".base" );
803 if ( section != null )
805 section.removeChangeListener( listener );
811 public void initialize()
814 this.postPolicies = componentContainer.buildMapWithRole( PostDownloadPolicy.class );
815 this.prePolicies = componentContainer.buildMapWithRole( PreDownloadPolicy.class );
816 this.downloadErrorPolicies = componentContainer.buildMapWithRole( DownloadErrorPolicy.class );
817 // Resolve expressions in the userConfigFilename and altConfigFilename
820 ExpressionEvaluator expressionEvaluator = new DefaultExpressionEvaluator();
821 expressionEvaluator.addExpressionSource( new SystemPropertyExpressionSource() );
822 String userConfigFileNameSysProps = System.getProperty( "archiva.user.configFileName" );
823 if ( StringUtils.isNotBlank( userConfigFileNameSysProps ) )
825 userConfigFilename = userConfigFileNameSysProps;
829 userConfigFilename = expressionEvaluator.expand( userConfigFilename );
831 altConfigFilename = expressionEvaluator.expand( altConfigFilename );
833 handleUpgradeConfiguration();
835 catch ( IndeterminateConfigurationException | RegistryException e )
837 throw new RuntimeException( "failed during upgrade from previous version" + e.getMessage(), e );
839 catch ( EvaluatorException e )
841 throw new RuntimeException(
842 "Unable to evaluate expressions found in " + "userConfigFilename or altConfigFilename.", e );
844 registry.addChangeListener( this );
848 * Handle upgrade to newer version
850 private void handleUpgradeConfiguration()
851 throws RegistryException, IndeterminateConfigurationException
854 List<String> dbConsumers = Arrays.asList( "update-db-artifact", "update-db-repository-metadata" );
856 // remove database consumers if here
857 List<String> intersec =
858 ListUtils.intersection( dbConsumers, configuration.getRepositoryScanning().getKnownContentConsumers() );
860 if ( !intersec.isEmpty() )
863 List<String> knowContentConsumers =
864 new ArrayList<>( configuration.getRepositoryScanning().getKnownContentConsumers().size() );
865 for ( String knowContentConsumer : configuration.getRepositoryScanning().getKnownContentConsumers() )
867 if ( !dbConsumers.contains( knowContentConsumer ) )
869 knowContentConsumers.add( knowContentConsumer );
873 configuration.getRepositoryScanning().setKnownContentConsumers( knowContentConsumers );
876 // ensure create-archiva-metadata is here
877 if ( !configuration.getRepositoryScanning().getKnownContentConsumers().contains( "create-archiva-metadata" ) )
879 List<String> knowContentConsumers =
880 new ArrayList<>( configuration.getRepositoryScanning().getKnownContentConsumers() );
881 knowContentConsumers.add( "create-archiva-metadata" );
882 configuration.getRepositoryScanning().setKnownContentConsumers( knowContentConsumers );
885 // ensure duplicate-artifacts is here
886 if ( !configuration.getRepositoryScanning().getKnownContentConsumers().contains( "duplicate-artifacts" ) )
888 List<String> knowContentConsumers =
889 new ArrayList<>( configuration.getRepositoryScanning().getKnownContentConsumers() );
890 knowContentConsumers.add( "duplicate-artifacts" );
891 configuration.getRepositoryScanning().setKnownContentConsumers( knowContentConsumers );
894 Registry defaultOnlyConfiguration = readDefaultOnlyConfiguration();
895 // Currently we check only for configuration version change, not certain version numbers.
896 if (hasConfigVersionChanged(configuration, defaultOnlyConfiguration)) {
897 updateCheckPathDefaults(configuration, defaultOnlyConfiguration);
898 String newVersion = defaultOnlyConfiguration.getString("version");
899 if (newVersion==null) {
900 throw new IndeterminateConfigurationException("The default configuration has no version information!");
902 configuration.setVersion(newVersion);
905 } catch (IndeterminateConfigurationException e) {
906 log.error("Error occured during configuration update to new version: {}", e.getMessage());
907 } catch (RegistryException e) {
908 log.error("Error occured during configuration update to new version: {}", e.getMessage());
916 this.configuration = null;
919 this.registry.initialize();
921 catch ( RegistryException e )
923 throw new ConfigurationRuntimeException( e.getMessage(), e );
929 public Locale getDefaultLocale( )
931 return defaultLocale;
935 public List<Locale.LanguageRange> getLanguagePriorities( )
937 return languagePriorities;
941 public Path getAppServerBaseDir() {
942 String basePath = registry.getString("appserver.base");
943 if (!StringUtils.isEmpty(basePath)) {
944 return Paths.get(basePath);
946 return Paths.get("");
951 public Path getRepositoryBaseDir() {
952 if (repositoryBaseDirectory==null) {
955 return repositoryBaseDirectory;
960 public Path getRemoteRepositoryBaseDir() {
961 if (remoteRepositoryBaseDirectory==null) {
964 return remoteRepositoryBaseDirectory;
968 public Path getDataDirectory() {
969 if (dataDirectory==null) {
972 return dataDirectory;
976 public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
978 // nothing to do here
982 public synchronized void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
984 configuration = null;
985 this.dataDirectory=null;
986 this.repositoryBaseDirectory=null;
989 private String removeExpressions( String directory )
991 String value = StringUtils.replace( directory, "${appserver.base}",
992 registry.getString( "appserver.base", "${appserver.base}" ) );
993 value = StringUtils.replace( value, "${appserver.home}",
994 registry.getString( "appserver.home", "${appserver.home}" ) );
998 private String unescapeCronExpression( String cronExpression )
1000 return StringUtils.replace( cronExpression, "\\,", "," );
1003 private String escapeCronExpression( String cronExpression )
1005 return StringUtils.replace( cronExpression, ",", "\\," );
1008 private Configuration unescapeExpressions( Configuration config )
1010 // TODO: for commons-configuration 1.3 only
1011 for ( ManagedRepositoryConfiguration c : config.getManagedRepositories() )
1013 c.setLocation( removeExpressions( c.getLocation() ) );
1014 c.setRefreshCronExpression( unescapeCronExpression( c.getRefreshCronExpression() ) );
1020 private Configuration checkRepositoryLocations( Configuration config )
1022 // additional check for [MRM-789], ensure that the location of the default repositories
1023 // are not installed in the server installation
1024 for ( ManagedRepositoryConfiguration repo : (List<ManagedRepositoryConfiguration>) config.getManagedRepositories() )
1026 String repoPath = repo.getLocation();
1027 Path repoLocation = Paths.get( repoPath );
1029 if ( Files.exists(repoLocation) && Files.isDirectory(repoLocation) && !repoPath.endsWith(
1030 "data/repositories/" + repo.getId() ) )
1032 repo.setLocation( repoPath + "/data/repositories/" + repo.getId() );
1039 public String getUserConfigFilename()
1041 return userConfigFilename;
1044 public String getAltConfigFilename()
1046 return altConfigFilename;
1050 public boolean isDefaulted()
1052 return this.isConfigurationDefaulted;
1055 public Registry getRegistry()
1060 public void setRegistry( Registry registry )
1062 this.registry = registry;
1066 public void setUserConfigFilename( String userConfigFilename )
1068 this.userConfigFilename = userConfigFilename;
1071 public void setAltConfigFilename( String altConfigFilename )
1073 this.altConfigFilename = altConfigFilename;