You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DefaultArchivaConfiguration.java 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. package org.apache.archiva.configuration;
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. */
  20. import org.apache.archiva.configuration.functors.ProxyConnectorConfigurationOrderComparator;
  21. import org.apache.archiva.configuration.io.registry.ConfigurationRegistryReader;
  22. import org.apache.archiva.configuration.io.registry.ConfigurationRegistryWriter;
  23. import org.apache.archiva.policies.AbstractUpdatePolicy;
  24. import org.apache.archiva.policies.CachedFailuresPolicy;
  25. import org.apache.archiva.policies.ChecksumPolicy;
  26. import org.apache.archiva.policies.DownloadErrorPolicy;
  27. import org.apache.archiva.policies.Policy;
  28. import org.apache.archiva.policies.PostDownloadPolicy;
  29. import org.apache.archiva.policies.PreDownloadPolicy;
  30. import org.apache.archiva.redback.components.evaluator.DefaultExpressionEvaluator;
  31. import org.apache.archiva.redback.components.evaluator.EvaluatorException;
  32. import org.apache.archiva.redback.components.evaluator.ExpressionEvaluator;
  33. import org.apache.archiva.redback.components.evaluator.sources.SystemPropertyExpressionSource;
  34. import org.apache.archiva.redback.components.registry.Registry;
  35. import org.apache.archiva.redback.components.registry.RegistryException;
  36. import org.apache.archiva.redback.components.registry.RegistryListener;
  37. import org.apache.archiva.redback.components.registry.commons.CommonsConfigurationRegistry;
  38. import org.apache.archiva.redback.components.springutils.ComponentContainer;
  39. import org.apache.commons.collections.CollectionUtils;
  40. import org.apache.commons.collections.ListUtils;
  41. import org.apache.commons.collections.MapUtils;
  42. import org.apache.commons.configuration.BaseConfiguration;
  43. import org.apache.commons.io.FileUtils;
  44. import org.apache.commons.lang.StringUtils;
  45. import org.slf4j.Logger;
  46. import org.slf4j.LoggerFactory;
  47. import org.springframework.stereotype.Service;
  48. import javax.annotation.PostConstruct;
  49. import javax.inject.Inject;
  50. import javax.inject.Named;
  51. import java.io.File;
  52. import java.io.IOException;
  53. import java.util.ArrayList;
  54. import java.util.Arrays;
  55. import java.util.Collection;
  56. import java.util.Collections;
  57. import java.util.HashMap;
  58. import java.util.HashSet;
  59. import java.util.Iterator;
  60. import java.util.List;
  61. import java.util.Map;
  62. import java.util.Map.Entry;
  63. import java.util.Set;
  64. /**
  65. * <p>
  66. * Implementation of configuration holder that retrieves it from the registry.
  67. * </p>
  68. * <p>
  69. * The registry layers and merges the 2 configuration files: user, and application server.
  70. * </p>
  71. * <p>
  72. * Instead of relying on the model defaults, if the registry is empty a default configuration file is loaded and
  73. * applied from a resource. The defaults are not loaded into the registry as the lists (eg repositories) could no longer
  74. * be removed if that was the case.
  75. * </p>
  76. * <p>
  77. * When saving the configuration, it is saved to the location it was read from. If it was read from the defaults, it
  78. * will be saved to the user location.
  79. * However, if the configuration contains information from both sources, an exception is raised as this is currently
  80. * unsupported. The reason for this is that it is not possible to identify where to re-save elements, and can result
  81. * in list configurations (eg repositories) becoming inconsistent.
  82. * </p>
  83. * <p>
  84. * If the configuration is outdated, it will be upgraded when it is loaded. This is done by checking the version flag
  85. * before reading it from the registry.
  86. * </p>
  87. */
  88. @Service ( "archivaConfiguration#default" )
  89. public class DefaultArchivaConfiguration
  90. implements ArchivaConfiguration, RegistryListener
  91. {
  92. private Logger log = LoggerFactory.getLogger( DefaultArchivaConfiguration.class );
  93. /**
  94. * Plexus registry to read the configuration from.
  95. */
  96. @Inject
  97. @Named ( value = "commons-configuration" )
  98. private Registry registry;
  99. @Inject
  100. private ComponentContainer componentContainer;
  101. /**
  102. * The configuration that has been converted.
  103. */
  104. private Configuration configuration;
  105. /**
  106. * see #initialize
  107. *
  108. * @todo these don't strictly belong in here
  109. */
  110. private Map<String, PreDownloadPolicy> prePolicies;
  111. /**
  112. * see #initialize
  113. *
  114. * @todo these don't strictly belong in here
  115. */
  116. private Map<String, PostDownloadPolicy> postPolicies;
  117. /**
  118. * see #initialize
  119. *
  120. * @todo these don't strictly belong in here
  121. */
  122. private Map<String, DownloadErrorPolicy> downloadErrorPolicies;
  123. /**
  124. * see #initialize
  125. * default-value="${user.home}/.m2/archiva.xml"
  126. */
  127. private String userConfigFilename = "${user.home}/.m2/archiva.xml";
  128. /**
  129. * see #initialize
  130. * default-value="${appserver.base}/conf/archiva.xml"
  131. */
  132. private String altConfigFilename = "${appserver.base}/conf/archiva.xml";
  133. /**
  134. * Configuration Listeners we've registered.
  135. */
  136. private Set<ConfigurationListener> listeners = new HashSet<ConfigurationListener>();
  137. /**
  138. * Registry Listeners we've registered.
  139. */
  140. private Set<RegistryListener> registryListeners = new HashSet<RegistryListener>();
  141. /**
  142. * Boolean to help determine if the configuration exists as a result of pulling in
  143. * the default-archiva.xml
  144. */
  145. private boolean isConfigurationDefaulted = false;
  146. private static final String KEY = "org.apache.archiva";
  147. public Configuration getConfiguration()
  148. {
  149. return loadConfiguration();
  150. }
  151. private synchronized Configuration loadConfiguration()
  152. {
  153. if ( configuration == null )
  154. {
  155. configuration = load();
  156. configuration = unescapeExpressions( configuration );
  157. if ( isConfigurationDefaulted )
  158. {
  159. configuration = checkRepositoryLocations( configuration );
  160. }
  161. }
  162. return configuration;
  163. }
  164. @SuppressWarnings ( "unchecked" )
  165. private Configuration load()
  166. {
  167. // TODO: should this be the same as section? make sure unnamed sections still work (eg, sys properties)
  168. Registry subset = registry.getSubset( KEY );
  169. if ( subset.getString( "version" ) == null )
  170. {
  171. // a little autodetection of v1, even if version is omitted (this was previously allowed)
  172. if ( subset.getSubset( "repositoryScanning" ).isEmpty() )
  173. {
  174. // only for empty, or v < 1
  175. subset = readDefaultConfiguration();
  176. }
  177. }
  178. Configuration config = new ConfigurationRegistryReader().read( subset );
  179. config.getRepositoryGroups();
  180. config.getRepositoryGroupsAsMap();
  181. if ( !config.getRepositories().isEmpty() )
  182. {
  183. for ( Iterator<V1RepositoryConfiguration> i = config.getRepositories().iterator(); i.hasNext(); )
  184. {
  185. V1RepositoryConfiguration r = i.next();
  186. r.setScanned( r.isIndexed() );
  187. if ( StringUtils.startsWith( r.getUrl(), "file://" ) )
  188. {
  189. r.setLocation( r.getUrl().substring( 7 ) );
  190. config.addManagedRepository( r );
  191. }
  192. else if ( StringUtils.startsWith( r.getUrl(), "file:" ) )
  193. {
  194. r.setLocation( r.getUrl().substring( 5 ) );
  195. config.addManagedRepository( r );
  196. }
  197. else if ( StringUtils.isEmpty( r.getUrl() ) )
  198. {
  199. // in case of empty url we can consider it as a managed one
  200. // check if location is null
  201. //file://${appserver.base}/repositories/${id}
  202. if ( StringUtils.isEmpty( r.getLocation() ) )
  203. {
  204. r.setLocation( "file://${appserver.base}/repositories/" + r.getId() );
  205. }
  206. config.addManagedRepository( r );
  207. }
  208. else
  209. {
  210. RemoteRepositoryConfiguration repo = new RemoteRepositoryConfiguration();
  211. repo.setId( r.getId() );
  212. repo.setLayout( r.getLayout() );
  213. repo.setName( r.getName() );
  214. repo.setUrl( r.getUrl() );
  215. config.addRemoteRepository( repo );
  216. }
  217. }
  218. // Prevent duplicate repositories from showing up.
  219. config.getRepositories().clear();
  220. registry.removeSubset( KEY + ".repositories" );
  221. }
  222. if ( !CollectionUtils.isEmpty( config.getRemoteRepositories() ) )
  223. {
  224. List<RemoteRepositoryConfiguration> remoteRepos = config.getRemoteRepositories();
  225. for ( RemoteRepositoryConfiguration repo : remoteRepos )
  226. {
  227. // [MRM-582] Remote Repositories with empty <username> and <password> fields shouldn't be created in configuration.
  228. if ( StringUtils.isBlank( repo.getUsername() ) )
  229. {
  230. repo.setUsername( null );
  231. }
  232. if ( StringUtils.isBlank( repo.getPassword() ) )
  233. {
  234. repo.setPassword( null );
  235. }
  236. }
  237. }
  238. if ( !config.getProxyConnectors().isEmpty() )
  239. {
  240. // Fix Proxy Connector Settings.
  241. // Create a copy of the list to read from (to prevent concurrent modification exceptions)
  242. List<ProxyConnectorConfiguration> proxyConnectorList =
  243. new ArrayList<>( config.getProxyConnectors() );
  244. // Remove the old connector list.
  245. config.getProxyConnectors().clear();
  246. for ( ProxyConnectorConfiguration connector : proxyConnectorList )
  247. {
  248. // Fix policies
  249. boolean connectorValid = true;
  250. Map<String, String> policies = new HashMap<String, String>();
  251. // Make copy of policies
  252. policies.putAll( connector.getPolicies() );
  253. // Clear out policies
  254. connector.getPolicies().clear();
  255. // Work thru policies. cleaning them up.
  256. for ( Entry<String, String> entry : policies.entrySet() )
  257. {
  258. String policyId = entry.getKey();
  259. String setting = entry.getValue();
  260. // Upgrade old policy settings.
  261. if ( "releases".equals( policyId ) || "snapshots".equals( policyId ) )
  262. {
  263. if ( "ignored".equals( setting ) )
  264. {
  265. setting = AbstractUpdatePolicy.ALWAYS;
  266. }
  267. else if ( "disabled".equals( setting ) )
  268. {
  269. setting = AbstractUpdatePolicy.NEVER;
  270. }
  271. }
  272. else if ( "cache-failures".equals( policyId ) )
  273. {
  274. if ( "ignored".equals( setting ) )
  275. {
  276. setting = CachedFailuresPolicy.NO;
  277. }
  278. else if ( "cached".equals( setting ) )
  279. {
  280. setting = CachedFailuresPolicy.YES;
  281. }
  282. }
  283. else if ( "checksum".equals( policyId ) )
  284. {
  285. if ( "ignored".equals( setting ) )
  286. {
  287. setting = ChecksumPolicy.IGNORE;
  288. }
  289. }
  290. // Validate existance of policy key.
  291. if ( policyExists( policyId ) )
  292. {
  293. Policy policy = findPolicy( policyId );
  294. // Does option exist?
  295. if ( !policy.getOptions().contains( setting ) )
  296. {
  297. setting = policy.getDefaultOption();
  298. }
  299. connector.addPolicy( policyId, setting );
  300. }
  301. else
  302. {
  303. // Policy key doesn't exist. Don't add it to golden version.
  304. log.warn( "Policy [{}] does not exist.", policyId );
  305. }
  306. }
  307. if ( connectorValid )
  308. {
  309. config.addProxyConnector( connector );
  310. }
  311. }
  312. // Normalize the order fields in the proxy connectors.
  313. Map<String, java.util.List<ProxyConnectorConfiguration>> proxyConnectorMap =
  314. config.getProxyConnectorAsMap();
  315. for ( List<ProxyConnectorConfiguration> connectors : proxyConnectorMap.values() )
  316. {
  317. // Sort connectors by order field.
  318. Collections.sort( connectors, ProxyConnectorConfigurationOrderComparator.getInstance() );
  319. // Normalize the order field values.
  320. int order = 1;
  321. for ( ProxyConnectorConfiguration connector : connectors )
  322. {
  323. connector.setOrder( order++ );
  324. }
  325. }
  326. }
  327. return config;
  328. }
  329. private Policy findPolicy( String policyId )
  330. {
  331. if ( MapUtils.isEmpty( prePolicies ) )
  332. {
  333. log.error( "No PreDownloadPolicies found!" );
  334. return null;
  335. }
  336. if ( MapUtils.isEmpty( postPolicies ) )
  337. {
  338. log.error( "No PostDownloadPolicies found!" );
  339. return null;
  340. }
  341. Policy policy;
  342. policy = prePolicies.get( policyId );
  343. if ( policy != null )
  344. {
  345. return policy;
  346. }
  347. policy = postPolicies.get( policyId );
  348. if ( policy != null )
  349. {
  350. return policy;
  351. }
  352. policy = downloadErrorPolicies.get( policyId );
  353. if ( policy != null )
  354. {
  355. return policy;
  356. }
  357. return null;
  358. }
  359. private boolean policyExists( String policyId )
  360. {
  361. if ( MapUtils.isEmpty( prePolicies ) )
  362. {
  363. log.error( "No PreDownloadPolicies found!" );
  364. return false;
  365. }
  366. if ( MapUtils.isEmpty( postPolicies ) )
  367. {
  368. log.error( "No PostDownloadPolicies found!" );
  369. return false;
  370. }
  371. return ( prePolicies.containsKey( policyId ) || postPolicies.containsKey( policyId )
  372. || downloadErrorPolicies.containsKey( policyId ) );
  373. }
  374. private Registry readDefaultConfiguration()
  375. {
  376. // if it contains some old configuration, remove it (Archiva 0.9)
  377. registry.removeSubset( KEY );
  378. try
  379. {
  380. registry.addConfigurationFromResource( "org/apache/archiva/configuration/default-archiva.xml", KEY );
  381. this.isConfigurationDefaulted = true;
  382. }
  383. catch ( RegistryException e )
  384. {
  385. throw new ConfigurationRuntimeException(
  386. "Fatal error: Unable to find the built-in default configuration and load it into the registry", e );
  387. }
  388. return registry.getSubset( KEY );
  389. }
  390. @SuppressWarnings ( "unchecked" )
  391. public synchronized void save( Configuration configuration )
  392. throws IndeterminateConfigurationException, RegistryException
  393. {
  394. Registry section = registry.getSection( KEY + ".user" );
  395. Registry baseSection = registry.getSection( KEY + ".base" );
  396. if ( section == null )
  397. {
  398. section = baseSection;
  399. if ( section == null )
  400. {
  401. section = createDefaultConfigurationFile();
  402. }
  403. }
  404. else if ( baseSection != null )
  405. {
  406. Collection<String> keys = baseSection.getKeys();
  407. boolean foundList = false;
  408. for ( Iterator<String> i = keys.iterator(); i.hasNext() && !foundList; )
  409. {
  410. String key = i.next();
  411. // a little aggressive with the repositoryScanning and databaseScanning - should be no need to split
  412. // that configuration
  413. if ( key.startsWith( "repositories" ) || key.startsWith( "proxyConnectors" ) || key.startsWith(
  414. "networkProxies" ) || key.startsWith( "repositoryScanning" ) || key.startsWith(
  415. "remoteRepositories" ) || key.startsWith( "managedRepositories" ) || key.startsWith(
  416. "repositoryGroups" ) )
  417. {
  418. foundList = true;
  419. }
  420. }
  421. if ( foundList )
  422. {
  423. this.configuration = null;
  424. throw new IndeterminateConfigurationException(
  425. "Configuration can not be saved when it is loaded from two sources" );
  426. }
  427. }
  428. // escape all cron expressions to handle ','
  429. escapeCronExpressions( configuration );
  430. // [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.
  431. if ( configuration.getManagedRepositories().isEmpty() && section != null )
  432. {
  433. section.removeSubset( "managedRepositories" );
  434. }
  435. if ( configuration.getRemoteRepositories().isEmpty() && section != null )
  436. {
  437. section.removeSubset( "remoteRepositories" );
  438. }
  439. if ( configuration.getProxyConnectors().isEmpty() && section != null )
  440. {
  441. section.removeSubset( "proxyConnectors" );
  442. }
  443. if ( configuration.getNetworkProxies().isEmpty() && section != null )
  444. {
  445. section.removeSubset( "networkProxies" );
  446. }
  447. if ( configuration.getLegacyArtifactPaths().isEmpty() && section != null )
  448. {
  449. section.removeSubset( "legacyArtifactPaths" );
  450. }
  451. if ( configuration.getRepositoryGroups().isEmpty() && section != null )
  452. {
  453. section.removeSubset( "repositoryGroups" );
  454. }
  455. if ( configuration.getRepositoryScanning() != null )
  456. {
  457. if ( configuration.getRepositoryScanning().getKnownContentConsumers().isEmpty() && section != null )
  458. {
  459. section.removeSubset( "repositoryScanning.knownContentConsumers" );
  460. }
  461. if ( configuration.getRepositoryScanning().getInvalidContentConsumers().isEmpty() && section != null )
  462. {
  463. section.removeSubset( "repositoryScanning.invalidContentConsumers" );
  464. }
  465. }
  466. new ConfigurationRegistryWriter().write( configuration, section );
  467. section.save();
  468. this.configuration = unescapeExpressions( configuration );
  469. triggerEvent( ConfigurationEvent.SAVED );
  470. }
  471. private void escapeCronExpressions( Configuration configuration )
  472. {
  473. for ( ManagedRepositoryConfiguration c : configuration.getManagedRepositories() )
  474. {
  475. c.setRefreshCronExpression( escapeCronExpression( c.getRefreshCronExpression() ) );
  476. }
  477. }
  478. private Registry createDefaultConfigurationFile()
  479. throws RegistryException
  480. {
  481. // TODO: may not be needed under commons-configuration 1.4 - check
  482. String contents = "<configuration />";
  483. String fileLocation = userConfigFilename;
  484. if ( !writeFile( "user configuration", userConfigFilename, contents ) )
  485. {
  486. fileLocation = altConfigFilename;
  487. if ( !writeFile( "alternative configuration", altConfigFilename, contents ) )
  488. {
  489. throw new RegistryException(
  490. "Unable to create configuration file in either user [" + userConfigFilename + "] or alternative ["
  491. + altConfigFilename
  492. + "] locations on disk, usually happens when not allowed to write to those locations." );
  493. }
  494. }
  495. // olamy hackish I know :-)
  496. contents = "<configuration><xml fileName=\"" + fileLocation
  497. + "\" config-forceCreate=\"true\" config-name=\"org.apache.archiva.user\"/>" + "</configuration>";
  498. ( (CommonsConfigurationRegistry) registry ).setProperties( contents );
  499. registry.initialize();
  500. for ( RegistryListener regListener : registryListeners )
  501. {
  502. addRegistryChangeListener( regListener );
  503. }
  504. triggerEvent( ConfigurationEvent.SAVED );
  505. Registry section = registry.getSection( KEY + ".user" );
  506. return section == null ? new CommonsConfigurationRegistry( new BaseConfiguration() ) : section;
  507. }
  508. /**
  509. * Attempts to write the contents to a file, if an IOException occurs, return false.
  510. * <p>
  511. * The file will be created if the directory to the file exists, otherwise this will return false.
  512. *
  513. * @param filetype the filetype (freeform text) to use in logging messages when failure to write.
  514. * @param path the path to write to.
  515. * @param contents the contents to write.
  516. * @return true if write successful.
  517. */
  518. private boolean writeFile( String filetype, String path, String contents )
  519. {
  520. File file = new File( path );
  521. try
  522. {
  523. // Check parent directory (if it is declared)
  524. if ( file.getParentFile() != null )
  525. {
  526. // Check that directory exists
  527. if ( ! file.getParentFile().isDirectory() )
  528. {
  529. // Directory to file must exist for file to be created
  530. return false;
  531. }
  532. }
  533. FileUtils.writeStringToFile( file, contents, "UTF-8" );
  534. return true;
  535. }
  536. catch ( IOException e )
  537. {
  538. log.error( "Unable to create " + filetype + " file: " + e.getMessage(), e );
  539. return false;
  540. }
  541. }
  542. private void triggerEvent( int type )
  543. {
  544. ConfigurationEvent evt = new ConfigurationEvent( type );
  545. for ( ConfigurationListener listener : listeners )
  546. {
  547. listener.configurationEvent( evt );
  548. }
  549. }
  550. public void addListener( ConfigurationListener listener )
  551. {
  552. if ( listener == null )
  553. {
  554. return;
  555. }
  556. listeners.add( listener );
  557. }
  558. public void removeListener( ConfigurationListener listener )
  559. {
  560. if ( listener == null )
  561. {
  562. return;
  563. }
  564. listeners.remove( listener );
  565. }
  566. public void addChangeListener( RegistryListener listener )
  567. {
  568. addRegistryChangeListener( listener );
  569. // keep track for later
  570. registryListeners.add( listener );
  571. }
  572. private void addRegistryChangeListener( RegistryListener listener )
  573. {
  574. Registry section = registry.getSection( KEY + ".user" );
  575. if ( section != null )
  576. {
  577. section.addChangeListener( listener );
  578. }
  579. section = registry.getSection( KEY + ".base" );
  580. if ( section != null )
  581. {
  582. section.addChangeListener( listener );
  583. }
  584. }
  585. @PostConstruct
  586. public void initialize()
  587. {
  588. this.postPolicies = componentContainer.buildMapWithRole( PostDownloadPolicy.class );
  589. this.prePolicies = componentContainer.buildMapWithRole( PreDownloadPolicy.class );
  590. this.downloadErrorPolicies = componentContainer.buildMapWithRole( DownloadErrorPolicy.class );
  591. // Resolve expressions in the userConfigFilename and altConfigFilename
  592. try
  593. {
  594. ExpressionEvaluator expressionEvaluator = new DefaultExpressionEvaluator();
  595. expressionEvaluator.addExpressionSource( new SystemPropertyExpressionSource() );
  596. String userConfigFileNameSysProps = System.getProperty( "archiva.user.configFileName" );
  597. if ( StringUtils.isNotBlank( userConfigFileNameSysProps ) )
  598. {
  599. userConfigFilename = userConfigFileNameSysProps;
  600. }
  601. else
  602. {
  603. userConfigFilename = expressionEvaluator.expand( userConfigFilename );
  604. }
  605. altConfigFilename = expressionEvaluator.expand( altConfigFilename );
  606. loadConfiguration();
  607. handleUpgradeConfiguration();
  608. }
  609. catch ( IndeterminateConfigurationException e )
  610. {
  611. throw new RuntimeException( "failed during upgrade from previous version" + e.getMessage(), e );
  612. }
  613. catch ( RegistryException e )
  614. {
  615. throw new RuntimeException( "failed during upgrade from previous version" + e.getMessage(), e );
  616. }
  617. catch ( EvaluatorException e )
  618. {
  619. throw new RuntimeException(
  620. "Unable to evaluate expressions found in " + "userConfigFilename or altConfigFilename.", e);
  621. }
  622. registry.addChangeListener( this );
  623. }
  624. /**
  625. * upgrade from 1.3
  626. */
  627. private void handleUpgradeConfiguration()
  628. throws RegistryException, IndeterminateConfigurationException
  629. {
  630. List<String> dbConsumers = Arrays.asList( "update-db-artifact", "update-db-repository-metadata" );
  631. // remove database consumers if here
  632. List<String> intersec =
  633. ListUtils.intersection( dbConsumers, configuration.getRepositoryScanning().getKnownContentConsumers() );
  634. if ( !intersec.isEmpty() )
  635. {
  636. List<String> knowContentConsumers =
  637. new ArrayList<>( configuration.getRepositoryScanning().getKnownContentConsumers().size() );
  638. for ( String knowContentConsumer : configuration.getRepositoryScanning().getKnownContentConsumers() )
  639. {
  640. if ( !dbConsumers.contains( knowContentConsumer ) )
  641. {
  642. knowContentConsumers.add( knowContentConsumer );
  643. }
  644. }
  645. configuration.getRepositoryScanning().setKnownContentConsumers( knowContentConsumers );
  646. }
  647. // ensure create-archiva-metadata is here
  648. if ( !configuration.getRepositoryScanning().getKnownContentConsumers().contains( "create-archiva-metadata" ) )
  649. {
  650. List<String> knowContentConsumers =
  651. new ArrayList<>( configuration.getRepositoryScanning().getKnownContentConsumers() );
  652. knowContentConsumers.add( "create-archiva-metadata" );
  653. configuration.getRepositoryScanning().setKnownContentConsumers( knowContentConsumers );
  654. }
  655. // ensure duplicate-artifacts is here
  656. if ( !configuration.getRepositoryScanning().getKnownContentConsumers().contains( "duplicate-artifacts" ) )
  657. {
  658. List<String> knowContentConsumers =
  659. new ArrayList<>( configuration.getRepositoryScanning().getKnownContentConsumers() );
  660. knowContentConsumers.add( "duplicate-artifacts" );
  661. configuration.getRepositoryScanning().setKnownContentConsumers( knowContentConsumers );
  662. }
  663. // save ??
  664. //save( configuration );
  665. }
  666. public void reload()
  667. {
  668. this.configuration = null;
  669. try
  670. {
  671. this.registry.initialize();
  672. }
  673. catch ( RegistryException e )
  674. {
  675. throw new ConfigurationRuntimeException( e.getMessage(), e );
  676. }
  677. this.initialize();
  678. }
  679. public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
  680. {
  681. // nothing to do here
  682. }
  683. public synchronized void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
  684. {
  685. configuration = null;
  686. }
  687. private String removeExpressions( String directory )
  688. {
  689. String value = StringUtils.replace( directory, "${appserver.base}",
  690. registry.getString( "appserver.base", "${appserver.base}" ) );
  691. value = StringUtils.replace( value, "${appserver.home}",
  692. registry.getString( "appserver.home", "${appserver.home}" ) );
  693. return value;
  694. }
  695. private String unescapeCronExpression( String cronExpression )
  696. {
  697. return StringUtils.replace( cronExpression, "\\,", "," );
  698. }
  699. private String escapeCronExpression( String cronExpression )
  700. {
  701. return StringUtils.replace( cronExpression, ",", "\\," );
  702. }
  703. private Configuration unescapeExpressions( Configuration config )
  704. {
  705. // TODO: for commons-configuration 1.3 only
  706. for ( Iterator<ManagedRepositoryConfiguration> i = config.getManagedRepositories().iterator(); i.hasNext(); )
  707. {
  708. ManagedRepositoryConfiguration c = i.next();
  709. c.setLocation( removeExpressions( c.getLocation() ) );
  710. c.setRefreshCronExpression( unescapeCronExpression( c.getRefreshCronExpression() ) );
  711. }
  712. return config;
  713. }
  714. private Configuration checkRepositoryLocations( Configuration config )
  715. {
  716. // additional check for [MRM-789], ensure that the location of the default repositories
  717. // are not installed in the server installation
  718. for ( ManagedRepositoryConfiguration repo : (List<ManagedRepositoryConfiguration>) config.getManagedRepositories() )
  719. {
  720. String repoPath = repo.getLocation();
  721. File repoLocation = new File( repoPath );
  722. if ( repoLocation.exists() && repoLocation.isDirectory() && !repoPath.endsWith(
  723. "data/repositories/" + repo.getId() ) )
  724. {
  725. repo.setLocation( repoPath + "/data/repositories/" + repo.getId() );
  726. }
  727. }
  728. return config;
  729. }
  730. public String getUserConfigFilename()
  731. {
  732. return userConfigFilename;
  733. }
  734. public String getAltConfigFilename()
  735. {
  736. return altConfigFilename;
  737. }
  738. public boolean isDefaulted()
  739. {
  740. return this.isConfigurationDefaulted;
  741. }
  742. public Registry getRegistry()
  743. {
  744. return registry;
  745. }
  746. public void setRegistry( Registry registry )
  747. {
  748. this.registry = registry;
  749. }
  750. public void setUserConfigFilename( String userConfigFilename )
  751. {
  752. this.userConfigFilename = userConfigFilename;
  753. }
  754. public void setAltConfigFilename( String altConfigFilename )
  755. {
  756. this.altConfigFilename = altConfigFilename;
  757. }
  758. }