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.components.evaluator.DefaultExpressionEvaluator;
29 import org.apache.archiva.components.evaluator.EvaluatorException;
30 import org.apache.archiva.components.evaluator.ExpressionEvaluator;
31 import org.apache.archiva.components.evaluator.sources.SystemPropertyExpressionSource;
32 import org.apache.archiva.components.registry.Registry;
33 import org.apache.archiva.components.registry.RegistryException;
34 import org.apache.archiva.components.registry.RegistryListener;
35 import org.apache.archiva.components.registry.commons.CommonsConfigurationRegistry;
36 import org.apache.commons.collections4.CollectionUtils;
37 import org.apache.commons.collections4.ListUtils;
38 import org.apache.commons.io.FileUtils;
39 import org.apache.commons.lang3.StringUtils;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42 import org.springframework.stereotype.Service;
44 import javax.annotation.PostConstruct;
45 import javax.inject.Inject;
46 import javax.inject.Named;
47 import java.io.IOException;
48 import java.nio.file.Files;
49 import java.nio.file.InvalidPathException;
50 import java.nio.file.Path;
51 import java.nio.file.Paths;
53 import java.util.Map.Entry;
57 * Implementation of configuration holder that retrieves it from the registry.
60 * The registry layers and merges the 2 configuration files: user, and application server.
63 * Instead of relying on the model defaults, if the registry is empty a default configuration file is loaded and
64 * applied from a resource. The defaults are not loaded into the registry as the lists (eg repositories) could no longer
65 * be removed if that was the case.
68 * When saving the configuration, it is saved to the location it was read from. If it was read from the defaults, it
69 * will be saved to the user location.
70 * However, if the configuration contains information from both sources, an exception is raised as this is currently
71 * unsupported. The reason for this is that it is not possible to identify where to re-save elements, and can result
72 * in list configurations (eg repositories) becoming inconsistent.
75 * If the configuration is outdated, it will be upgraded when it is loaded. This is done by checking the version flag
76 * before reading it from the registry.
78 * FIXME: The synchronization must be improved, the current impl may lead to inconsistent data or multiple getConfiguration() calls (martin_s@apache.org)
81 @Service("archivaConfiguration#default")
82 public class DefaultArchivaConfiguration
83 implements ArchivaConfiguration, RegistryListener {
84 private final Logger log = LoggerFactory.getLogger(DefaultArchivaConfiguration.class);
86 private static String FILE_ENCODING = "UTF-8";
89 * Plexus registry to read the configuration from.
92 @Named(value = "commons-configuration")
93 private Registry registry;
96 * The configuration that has been converted.
98 private Configuration configuration;
102 * default-value="${user.home}/.m2/archiva.xml"
104 private String userConfigFilename = "${user.home}/.m2/archiva.xml";
108 * default-value="${appserver.base}/conf/archiva.xml"
110 private String altConfigFilename = "${appserver.base}/conf/archiva.xml";
113 * Configuration Listeners we've registered.
115 private Set<ConfigurationListener> listeners = new HashSet<>();
118 * Registry Listeners we've registered.
120 private Set<RegistryListener> registryListeners = new HashSet<>();
123 * Boolean to help determine if the configuration exists as a result of pulling in
124 * the default-archiva.xml
126 private boolean isConfigurationDefaulted = false;
128 private static final String KEY = "org.apache.archiva";
130 // Section used for default only configuration
131 private static final String KEY_DEFAULT_ONLY = "org.apache.archiva_default";
133 private Locale defaultLocale = Locale.getDefault();
135 private List<Locale.LanguageRange> languagePriorities = new ArrayList<>();
137 private volatile Path dataDirectory;
138 private volatile Path repositoryBaseDirectory;
139 private volatile Path remoteRepositoryBaseDirectory;
140 private volatile Path repositoryGroupBaseDirectory;
143 private void init() {
144 languagePriorities = Locale.LanguageRange.parse("en,fr,de");
149 public Configuration getConfiguration() {
150 return loadConfiguration();
153 private synchronized Configuration loadConfiguration() {
154 if (configuration == null) {
155 configuration = load();
156 configuration = unescapeExpressions(configuration);
157 if (isConfigurationDefaulted) {
158 configuration = checkRepositoryLocations(configuration);
162 return configuration;
165 private boolean hasConfigVersionChanged(Configuration current, Registry defaultOnlyConfiguration) {
166 return current == null || current.getVersion() == null ||
167 !current.getVersion().trim().equals(defaultOnlyConfiguration.getString("version", "").trim());
170 @SuppressWarnings("unchecked")
171 private Configuration load() {
172 // TODO: should this be the same as section? make sure unnamed sections still work (eg, sys properties)
173 Registry subset = registry.getSubset(KEY);
174 if (subset.getString("version") == null) {
175 if (subset.getSubset("repositoryScanning").isEmpty()) {
177 subset = readDefaultConfiguration();
179 throw new RuntimeException("No version tag found in configuration. Archiva configuration version 1.x is not longer supported.");
183 Configuration config = new ConfigurationRegistryReader().read(subset);
185 // Resolving data and repositories directories
186 // If the config entries are absolute, the path is used as it is
187 // if the config entries are empty, they are resolved:
188 // dataDirectory = ${appserver.base}/data
189 // repositoryDirectory = ${dataDirectory}/repositories
190 // If the entries are relative they are resolved
191 // relative to the appserver.base, for dataDirectory
192 // relative to dataDirectory for repositoryBase
193 String dataDir = config.getArchivaRuntimeConfiguration().getDataDirectory();
194 if (StringUtils.isEmpty(dataDir)) {
195 dataDirectory = getAppServerBaseDir().resolve("data");
197 Path tmpDataDir = Paths.get(dataDir);
198 if (tmpDataDir.isAbsolute()) {
199 dataDirectory = tmpDataDir;
201 dataDirectory = getAppServerBaseDir().resolve(tmpDataDir);
204 config.getArchivaRuntimeConfiguration().setDataDirectory(dataDirectory.normalize().toString());
205 String repoBaseDir = config.getArchivaRuntimeConfiguration().getRepositoryBaseDirectory();
206 if (StringUtils.isEmpty(repoBaseDir)) {
207 repositoryBaseDirectory = dataDirectory.resolve("repositories");
210 Path tmpRepoBaseDir = Paths.get(repoBaseDir);
211 if (tmpRepoBaseDir.isAbsolute()) {
212 repositoryBaseDirectory = tmpRepoBaseDir;
214 dataDirectory.resolve(tmpRepoBaseDir);
218 String remoteRepoBaseDir = config.getArchivaRuntimeConfiguration().getRemoteRepositoryBaseDirectory();
219 if (StringUtils.isEmpty(remoteRepoBaseDir)) {
220 remoteRepositoryBaseDirectory = dataDirectory.resolve("remotes");
222 Path tmpRemoteRepoDir = Paths.get(remoteRepoBaseDir);
223 if (tmpRemoteRepoDir.isAbsolute()) {
224 remoteRepositoryBaseDirectory = tmpRemoteRepoDir;
226 dataDirectory.resolve(tmpRemoteRepoDir);
230 String repositoryGroupBaseDir = config.getArchivaRuntimeConfiguration().getRepositoryGroupBaseDirectory();
231 if (StringUtils.isEmpty(repositoryGroupBaseDir)) {
232 repositoryGroupBaseDirectory = dataDirectory.resolve("groups");
234 Path tmpGroupDir = Paths.get(repositoryGroupBaseDir);
235 if (tmpGroupDir.isAbsolute()) {
236 repositoryGroupBaseDirectory = tmpGroupDir;
238 dataDirectory.resolve(tmpGroupDir);
243 config.getRepositoryGroups();
244 config.getRepositoryGroupsAsMap();
245 if (!CollectionUtils.isEmpty(config.getRemoteRepositories())) {
246 List<RemoteRepositoryConfiguration> remoteRepos = config.getRemoteRepositories();
247 for (RemoteRepositoryConfiguration repo : remoteRepos) {
248 // [MRM-582] Remote Repositories with empty <username> and <password> fields shouldn't be created in configuration.
249 if (StringUtils.isBlank(repo.getUsername())) {
250 repo.setUsername(null);
253 if (StringUtils.isBlank(repo.getPassword())) {
254 repo.setPassword(null);
259 if (!config.getProxyConnectors().isEmpty()) {
260 // Fix Proxy Connector Settings.
262 // Create a copy of the list to read from (to prevent concurrent modification exceptions)
263 List<ProxyConnectorConfiguration> proxyConnectorList = new ArrayList<>(config.getProxyConnectors());
264 // Remove the old connector list.
265 config.getProxyConnectors().clear();
267 for (ProxyConnectorConfiguration connector : proxyConnectorList) {
269 boolean connectorValid = true;
271 Map<String, String> policies = new HashMap<>();
272 // Make copy of policies
273 policies.putAll(connector.getPolicies());
274 // Clear out policies
275 connector.getPolicies().clear();
277 // Work thru policies. cleaning them up.
278 for (Entry<String, String> entry : policies.entrySet()) {
279 String policyId = entry.getKey();
280 String setting = entry.getValue();
282 // Upgrade old policy settings.
283 if ("releases".equals(policyId) || "snapshots".equals(policyId)) {
284 if ("ignored".equals(setting)) {
285 setting = AbstractUpdatePolicy.ALWAYS.getId();
286 } else if ("disabled".equals(setting)) {
287 setting = AbstractUpdatePolicy.NEVER.getId();
289 } else if ("cache-failures".equals(policyId)) {
290 if ("ignored".equals(setting)) {
291 setting = CachedFailuresPolicy.NO.getId();
292 } else if ("cached".equals(setting)) {
293 setting = CachedFailuresPolicy.YES.getId();
295 } else if ("checksum".equals(policyId)) {
296 if ("ignored".equals(setting)) {
297 setting = ChecksumPolicy.IGNORE.getId();
301 // Validate existance of policy key.
302 connector.addPolicy(policyId, setting);
305 if (connectorValid) {
306 config.addProxyConnector(connector);
310 // Normalize the order fields in the proxy connectors.
311 Map<String, java.util.List<ProxyConnectorConfiguration>> proxyConnectorMap =
312 config.getProxyConnectorAsMap();
314 for (List<ProxyConnectorConfiguration> connectors : proxyConnectorMap.values()) {
315 // Sort connectors by order field.
316 Collections.sort(connectors, ProxyConnectorConfigurationOrderComparator.getInstance());
318 // Normalize the order field values.
320 for (ProxyConnectorConfiguration connector : connectors) {
321 connector.setOrder(order++);
326 this.defaultLocale = Locale.forLanguageTag(config.getArchivaRuntimeConfiguration().getDefaultLanguage());
327 this.languagePriorities = Locale.LanguageRange.parse(config.getArchivaRuntimeConfiguration().getLanguageRange());
332 * Updates the checkpath list for repositories.
334 * We are replacing existing ones and adding new ones. This allows to update the list with new releases.
336 * We are also updating existing remote repositories, if they exist already.
338 * This update method should only be called, if the config version changes to avoid overwriting
339 * user repository settings all the time.
341 private void updateCheckPathDefaults(Configuration config, Registry defaultConfiguration) {
342 List<RepositoryCheckPath> existingCheckPathList = config.getArchivaDefaultConfiguration().getDefaultCheckPaths();
343 HashMap<String, RepositoryCheckPath> existingCheckPaths = new HashMap<>();
344 HashMap<String, RepositoryCheckPath> newCheckPaths = new HashMap<>();
345 for (RepositoryCheckPath path : config.getArchivaDefaultConfiguration().getDefaultCheckPaths()) {
346 existingCheckPaths.put(path.getUrl(), path);
348 List defaultCheckPathsSubsets = defaultConfiguration.getSubsetList("archivaDefaultConfiguration.defaultCheckPaths.defaultCheckPath");
349 for (Iterator i = defaultCheckPathsSubsets.iterator(); i.hasNext(); ) {
350 RepositoryCheckPath v = readRepositoryCheckPath((Registry) i.next());
351 if (existingCheckPaths.containsKey(v.getUrl())) {
352 existingCheckPathList.remove(existingCheckPaths.get(v.getUrl()));
354 existingCheckPathList.add(v);
355 newCheckPaths.put(v.getUrl(), v);
357 // Remote repositories update
358 for (RemoteRepositoryConfiguration remoteRepositoryConfiguration : config.getRemoteRepositories()) {
359 String url = remoteRepositoryConfiguration.getUrl().toLowerCase();
360 if (newCheckPaths.containsKey(url)) {
361 String currentPath = remoteRepositoryConfiguration.getCheckPath();
362 String newPath = newCheckPaths.get(url).getPath();
363 log.info("Updating connection check path for repository {}, from '{}' to '{}'.", remoteRepositoryConfiguration.getId(),
364 currentPath, newPath);
365 remoteRepositoryConfiguration.setCheckPath(newPath);
370 private RepositoryCheckPath readRepositoryCheckPath(Registry registry) {
371 RepositoryCheckPath value = new RepositoryCheckPath();
373 String url = registry.getString("url", value.getUrl());
376 String path = registry.getString("path", value.getPath());
382 private Registry readDefaultConfiguration() {
383 // if it contains some old configuration, remove it (Archiva 0.9)
384 registry.removeSubset(KEY);
387 registry.addConfigurationFromResource("org/apache/archiva/configuration/default-archiva.xml", KEY);
388 this.isConfigurationDefaulted = true;
389 } catch (RegistryException e) {
390 throw new ConfigurationRuntimeException(
391 "Fatal error: Unable to find the built-in default configuration and load it into the registry", e);
393 return registry.getSubset(KEY);
397 * Reads the default only configuration into a special prefix. This allows to check for changes
398 * of the default configuration.
400 private Registry readDefaultOnlyConfiguration() {
401 registry.removeSubset(KEY_DEFAULT_ONLY);
403 registry.addConfigurationFromResource("org/apache/archiva/configuration/default-archiva.xml", KEY_DEFAULT_ONLY);
404 } catch (RegistryException e) {
405 throw new ConfigurationRuntimeException(
406 "Fatal error: Unable to find the built-in default configuration and load it into the registry", e);
408 return registry.getSubset(KEY_DEFAULT_ONLY);
411 @SuppressWarnings("unchecked")
413 public synchronized void save(Configuration configuration) throws IndeterminateConfigurationException, RegistryException
415 save( configuration, "" );
419 * Saves the configuration and adds the given tag to the event.
420 * @param configuration the configuration to save
421 * @param eventTag the tag to add to the configuration saved event
422 * @throws IndeterminateConfigurationException if the
423 * @throws RegistryException
426 public synchronized void save(Configuration configuration, String eventTag)
427 throws IndeterminateConfigurationException, RegistryException {
428 Registry section = registry.getSection(KEY + ".user");
429 Registry baseSection = registry.getSection(KEY + ".base");
430 if (section == null) {
431 section = baseSection;
432 if (section == null) {
433 section = createDefaultConfigurationFile(eventTag);
435 } else if (baseSection != null) {
436 Collection<String> keys = baseSection.getKeys();
437 boolean foundList = false;
438 for (Iterator<String> i = keys.iterator(); i.hasNext() && !foundList; ) {
439 String key = i.next();
441 // a little aggressive with the repositoryScanning and databaseScanning - should be no need to split
442 // that configuration
443 if (key.startsWith("repositories") //
444 || key.startsWith("proxyConnectors") //
445 || key.startsWith("networkProxies") //
446 || key.startsWith("repositoryScanning") //
447 || key.startsWith("remoteRepositories") //
448 || key.startsWith("managedRepositories") //
449 || key.startsWith("repositoryGroups")) //
456 this.configuration = null;
458 throw new IndeterminateConfigurationException(
459 "Configuration can not be saved when it is loaded from two sources");
463 // escape all cron expressions to handle ','
464 escapeCronExpressions(configuration);
466 // [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.
467 if (section != null) {
468 if (configuration.getManagedRepositories().isEmpty()) {
469 section.removeSubset("managedRepositories");
471 if (configuration.getRemoteRepositories().isEmpty()) {
472 section.removeSubset("remoteRepositories");
475 if (configuration.getProxyConnectors().isEmpty()) {
476 section.removeSubset("proxyConnectors");
478 if (configuration.getNetworkProxies().isEmpty()) {
479 section.removeSubset("networkProxies");
481 if (configuration.getLegacyArtifactPaths().isEmpty()) {
482 section.removeSubset("legacyArtifactPaths");
484 if (configuration.getRepositoryGroups().isEmpty()) {
485 section.removeSubset("repositoryGroups");
487 if (configuration.getRepositoryScanning() != null) {
488 if (configuration.getRepositoryScanning().getKnownContentConsumers().isEmpty()) {
489 section.removeSubset("repositoryScanning.knownContentConsumers");
491 if (configuration.getRepositoryScanning().getInvalidContentConsumers().isEmpty()) {
492 section.removeSubset("repositoryScanning.invalidContentConsumers");
495 if (configuration.getArchivaRuntimeConfiguration() != null) {
496 section.removeSubset("archivaRuntimeConfiguration.defaultCheckPaths");
499 new ConfigurationRegistryWriter().write(configuration, section);
504 this.configuration = unescapeExpressions(configuration);
505 isConfigurationDefaulted = false;
507 triggerEvent(ConfigurationEvent.SAVED, eventTag);
510 private void escapeCronExpressions(Configuration configuration) {
511 for (ManagedRepositoryConfiguration c : configuration.getManagedRepositories()) {
512 c.setRefreshCronExpression(escapeCronExpression(c.getRefreshCronExpression()));
516 private Registry createDefaultConfigurationFile(String eventTag)
517 throws RegistryException {
518 // TODO: may not be needed under commons-configuration 1.4 - check
520 String contents = "<configuration />";
522 String fileLocation = userConfigFilename;
524 if (!writeFile("user configuration", userConfigFilename, contents)) {
525 fileLocation = altConfigFilename;
526 if (!writeFile("alternative configuration", altConfigFilename, contents, true)) {
527 throw new RegistryException(
528 "Unable to create configuration file in either user [" + userConfigFilename + "] or alternative ["
530 + "] locations on disk, usually happens when not allowed to write to those locations.");
534 // olamy hackish I know :-)
535 contents = "<configuration><xml fileName=\"" + fileLocation
536 + "\" config-forceCreate=\"true\" config-name=\"org.apache.archiva.user\"/>" + "</configuration>";
538 ((CommonsConfigurationRegistry) registry).setInitialConfiguration(contents);
540 registry.initialize();
542 for (RegistryListener regListener : registryListeners) {
543 addRegistryChangeListener(regListener);
546 triggerEvent(ConfigurationEvent.SAVED, eventTag==null?"default-file":eventTag);
548 Registry section = registry.getSection(KEY + ".user");
549 if (section == null) {
550 return new CommonsConfigurationRegistry( );
556 private boolean writeFile(String filetype, String path, String contents) {
557 return writeFile( filetype, path, contents, false );
561 * Attempts to write the contents to a file, if an IOException occurs, return false.
563 * The file will be created if the directory to the file exists, otherwise this will return false.
565 * @param filetype the filetype (freeform text) to use in logging messages when failure to write.
566 * @param path the path to write to.
567 * @param contents the contents to write.
568 * @return true if write successful.
570 private boolean writeFile(String filetype, String path, String contents, boolean createDirs) {
572 Path file = Paths.get(path);
573 // Check parent directory (if it is declared)
574 final Path parent = file.getParent();
575 if (parent != null) {
576 // Check that directory exists
577 if (!Files.exists( parent ) && createDirs) {
578 Files.createDirectories( parent );
580 if (!Files.isDirectory(parent)) {
581 // Directory to file must exist for file to be created
585 FileUtils.writeStringToFile(file.toFile(), contents, FILE_ENCODING);
587 } catch (IOException e) {
588 log.error("Unable to create {} file: {}", filetype, e.getMessage(), e);
590 } catch (InvalidPathException ipe) {
591 log.error("Unable to read {} file: {}", path, ipe.getMessage(), ipe);
596 private void triggerEvent(int type, String eventTag) {
597 ConfigurationEvent evt = new ConfigurationEvent(type, eventTag);
598 for (ConfigurationListener listener : listeners) {
599 listener.configurationEvent(evt);
604 public void addListener(ConfigurationListener listener) {
605 if (listener == null) {
609 listeners.add(listener);
613 public void removeListener(ConfigurationListener listener) {
614 if (listener == null) {
618 listeners.remove(listener);
623 public void addChangeListener(RegistryListener listener) {
624 addRegistryChangeListener(listener);
626 // keep track for later
627 registryListeners.add(listener);
630 private void addRegistryChangeListener(RegistryListener listener) {
631 Registry section = registry.getSection(KEY + ".user");
632 if (section != null) {
633 section.addChangeListener(listener);
635 section = registry.getSection(KEY + ".base");
636 if (section != null) {
637 section.addChangeListener(listener);
642 public void removeChangeListener(RegistryListener listener) {
643 boolean removed = registryListeners.remove(listener);
644 log.debug("RegistryListener: '{}' removed {}", listener, removed);
646 Registry section = registry.getSection(KEY + ".user");
647 if (section != null) {
648 section.removeChangeListener(listener);
650 section = registry.getSection(KEY + ".base");
651 if (section != null) {
652 section.removeChangeListener(listener);
658 public void initialize() {
660 // Resolve expressions in the userConfigFilename and altConfigFilename
662 ExpressionEvaluator expressionEvaluator = new DefaultExpressionEvaluator();
663 expressionEvaluator.addExpressionSource(new SystemPropertyExpressionSource());
664 String userConfigFileNameSysProps = System.getProperty(USER_CONFIG_PROPERTY);
665 if (StringUtils.isNotBlank(userConfigFileNameSysProps)) {
666 userConfigFilename = userConfigFileNameSysProps;
668 String userConfigFileNameEnv = System.getenv(USER_CONFIG_ENVVAR);
669 if (StringUtils.isNotBlank(userConfigFileNameEnv)) {
670 userConfigFilename = userConfigFileNameEnv;
672 userConfigFilename = expressionEvaluator.expand(userConfigFilename);
675 altConfigFilename = expressionEvaluator.expand(altConfigFilename);
677 handleUpgradeConfiguration();
678 } catch (IndeterminateConfigurationException | RegistryException e) {
679 throw new RuntimeException("failed during upgrade from previous version" + e.getMessage(), e);
680 } catch (EvaluatorException e) {
681 throw new RuntimeException(
682 "Unable to evaluate expressions found in " + "userConfigFilename or altConfigFilename.", e);
684 registry.addChangeListener(this);
688 * Handle upgrade to newer version
690 private void handleUpgradeConfiguration()
691 throws RegistryException, IndeterminateConfigurationException {
693 List<String> dbConsumers = Arrays.asList("update-db-artifact", "update-db-repository-metadata");
695 // remove database consumers if here
696 List<String> intersec =
697 ListUtils.intersection(dbConsumers, configuration.getRepositoryScanning().getKnownContentConsumers());
699 if (!intersec.isEmpty()) {
701 List<String> knowContentConsumers =
702 new ArrayList<>(configuration.getRepositoryScanning().getKnownContentConsumers().size());
703 for (String knowContentConsumer : configuration.getRepositoryScanning().getKnownContentConsumers()) {
704 if (!dbConsumers.contains(knowContentConsumer)) {
705 knowContentConsumers.add(knowContentConsumer);
709 configuration.getRepositoryScanning().setKnownContentConsumers(knowContentConsumers);
712 // ensure create-archiva-metadata is here
713 if (!configuration.getRepositoryScanning().getKnownContentConsumers().contains("create-archiva-metadata")) {
714 List<String> knowContentConsumers =
715 new ArrayList<>(configuration.getRepositoryScanning().getKnownContentConsumers());
716 knowContentConsumers.add("create-archiva-metadata");
717 configuration.getRepositoryScanning().setKnownContentConsumers(knowContentConsumers);
720 // ensure duplicate-artifacts is here
721 if (!configuration.getRepositoryScanning().getKnownContentConsumers().contains("duplicate-artifacts")) {
722 List<String> knowContentConsumers =
723 new ArrayList<>(configuration.getRepositoryScanning().getKnownContentConsumers());
724 knowContentConsumers.add("duplicate-artifacts");
725 configuration.getRepositoryScanning().setKnownContentConsumers(knowContentConsumers);
728 Registry defaultOnlyConfiguration = readDefaultOnlyConfiguration();
729 // Currently we check only for configuration version change, not certain version numbers.
730 if (hasConfigVersionChanged(configuration, defaultOnlyConfiguration)) {
731 updateCheckPathDefaults(configuration, defaultOnlyConfiguration);
732 String newVersion = defaultOnlyConfiguration.getString("version");
733 if (newVersion == null) {
734 throw new IndeterminateConfigurationException("The default configuration has no version information!");
736 configuration.setVersion(newVersion);
739 } catch (IndeterminateConfigurationException e) {
740 log.error("Error occured during configuration update to new version: {}", e.getMessage());
741 } catch (RegistryException e) {
742 log.error("Error occured during configuration update to new version: {}", e.getMessage());
748 public void reload() {
749 this.configuration = null;
751 this.registry.initialize();
752 } catch (RegistryException e) {
753 throw new ConfigurationRuntimeException(e.getMessage(), e);
759 public Locale getDefaultLocale() {
760 return defaultLocale;
764 public List<Locale.LanguageRange> getLanguagePriorities() {
765 return languagePriorities;
769 public Path getAppServerBaseDir() {
770 String basePath = registry.getString("appserver.base");
771 if (!StringUtils.isEmpty(basePath)) {
772 return Paths.get(basePath);
774 return Paths.get("");
779 public Path getRepositoryBaseDir() {
780 if (repositoryBaseDirectory == null) {
783 return repositoryBaseDirectory;
788 public Path getRemoteRepositoryBaseDir() {
789 if (remoteRepositoryBaseDirectory == null) {
792 return remoteRepositoryBaseDirectory;
796 public Path getRepositoryGroupBaseDir() {
797 if (repositoryGroupBaseDirectory == null) {
800 return repositoryGroupBaseDirectory;
804 public Path getDataDirectory() {
805 if (dataDirectory == null) {
808 return dataDirectory;
812 public void beforeConfigurationChange(Registry registry, String propertyName, Object propertyValue) {
813 // nothing to do here
817 public synchronized void afterConfigurationChange(Registry registry, String propertyName, Object propertyValue) {
818 // configuration = null;
819 // this.dataDirectory = null;
820 // this.repositoryBaseDirectory = null;
823 private String removeExpressions(String directory) {
824 String value = StringUtils.replace(directory, "${appserver.base}",
825 registry.getString("appserver.base", "${appserver.base}"));
826 value = StringUtils.replace(value, "${appserver.home}",
827 registry.getString("appserver.home", "${appserver.home}"));
831 private String unescapeCronExpression(String cronExpression) {
832 return StringUtils.replace(cronExpression, "\\,", ",");
835 private String escapeCronExpression(String cronExpression) {
836 return StringUtils.replace(cronExpression, ",", "\\,");
839 private Configuration unescapeExpressions(Configuration config) {
840 // TODO: for commons-configuration 1.3 only
841 for (ManagedRepositoryConfiguration c : config.getManagedRepositories()) {
842 c.setLocation(removeExpressions(c.getLocation()));
843 c.setRefreshCronExpression(unescapeCronExpression(c.getRefreshCronExpression()));
849 private Configuration checkRepositoryLocations(Configuration config) {
850 // additional check for [MRM-789], ensure that the location of the default repositories
851 // are not installed in the server installation
852 for (ManagedRepositoryConfiguration repo : (List<ManagedRepositoryConfiguration>) config.getManagedRepositories()) {
853 String repoPath = repo.getLocation();
854 Path repoLocation = Paths.get(repoPath);
856 if (Files.exists(repoLocation) && Files.isDirectory(repoLocation) && !repoPath.endsWith(
857 "/repositories/" + repo.getId())) {
858 repo.setLocation(repoPath + "/data/repositories/" + repo.getId());
865 public String getUserConfigFilename() {
866 return userConfigFilename;
869 public String getAltConfigFilename() {
870 return altConfigFilename;
874 public boolean isDefaulted() {
875 return this.isConfigurationDefaulted;
878 public Registry getRegistry() {
882 public void setRegistry(Registry registry) {
883 this.registry = registry;
887 public void setUserConfigFilename(String userConfigFilename) {
888 this.userConfigFilename = userConfigFilename;
891 public void setAltConfigFilename(String altConfigFilename) {
892 this.altConfigFilename = altConfigFilename;