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.

DefaultRepositoryProxyConnectors.java 53KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415
  1. package org.apache.archiva.proxy;
  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.admin.model.RepositoryAdminException;
  21. import org.apache.archiva.admin.model.beans.NetworkProxy;
  22. import org.apache.archiva.admin.model.beans.ProxyConnectorRuleType;
  23. import org.apache.archiva.admin.model.networkproxy.NetworkProxyAdmin;
  24. import org.apache.archiva.common.filelock.FileLockException;
  25. import org.apache.archiva.common.filelock.FileLockManager;
  26. import org.apache.archiva.common.filelock.FileLockTimeoutException;
  27. import org.apache.archiva.common.filelock.Lock;
  28. import org.apache.archiva.configuration.ArchivaConfiguration;
  29. import org.apache.archiva.configuration.Configuration;
  30. import org.apache.archiva.configuration.ConfigurationNames;
  31. import org.apache.archiva.configuration.NetworkProxyConfiguration;
  32. import org.apache.archiva.configuration.ProxyConnectorConfiguration;
  33. import org.apache.archiva.configuration.ProxyConnectorRuleConfiguration;
  34. import org.apache.archiva.model.ArtifactReference;
  35. import org.apache.archiva.model.Keys;
  36. import org.apache.archiva.model.RepositoryURL;
  37. import org.apache.archiva.policies.DownloadErrorPolicy;
  38. import org.apache.archiva.policies.DownloadPolicy;
  39. import org.apache.archiva.policies.PolicyConfigurationException;
  40. import org.apache.archiva.policies.PolicyViolationException;
  41. import org.apache.archiva.policies.PostDownloadPolicy;
  42. import org.apache.archiva.policies.PreDownloadPolicy;
  43. import org.apache.archiva.policies.ProxyDownloadException;
  44. import org.apache.archiva.policies.urlcache.UrlFailureCache;
  45. import org.apache.archiva.proxy.common.WagonFactory;
  46. import org.apache.archiva.proxy.common.WagonFactoryException;
  47. import org.apache.archiva.proxy.common.WagonFactoryRequest;
  48. import org.apache.archiva.proxy.model.ProxyConnector;
  49. import org.apache.archiva.proxy.model.ProxyFetchResult;
  50. import org.apache.archiva.proxy.model.RepositoryProxyConnectors;
  51. import org.apache.archiva.redback.components.registry.Registry;
  52. import org.apache.archiva.redback.components.registry.RegistryListener;
  53. import org.apache.archiva.redback.components.taskqueue.TaskQueueException;
  54. import org.apache.archiva.repository.ManagedRepository;
  55. import org.apache.archiva.repository.ManagedRepositoryContent;
  56. import org.apache.archiva.repository.PasswordCredentials;
  57. import org.apache.archiva.repository.RemoteRepository;
  58. import org.apache.archiva.repository.RemoteRepositoryContent;
  59. import org.apache.archiva.repository.RepositoryContentFactory;
  60. import org.apache.archiva.repository.RepositoryCredentials;
  61. import org.apache.archiva.repository.RepositoryRegistry;
  62. import org.apache.archiva.repository.metadata.MetadataTools;
  63. import org.apache.archiva.repository.metadata.RepositoryMetadataException;
  64. import org.apache.archiva.scheduler.ArchivaTaskScheduler;
  65. import org.apache.archiva.scheduler.repository.model.RepositoryTask;
  66. import org.apache.commons.collections.CollectionUtils;
  67. import org.apache.commons.io.FilenameUtils;
  68. import org.apache.commons.lang.StringUtils;
  69. import org.apache.commons.lang.SystemUtils;
  70. import org.apache.maven.wagon.ConnectionException;
  71. import org.apache.maven.wagon.ResourceDoesNotExistException;
  72. import org.apache.maven.wagon.Wagon;
  73. import org.apache.maven.wagon.WagonException;
  74. import org.apache.maven.wagon.authentication.AuthenticationException;
  75. import org.apache.maven.wagon.authentication.AuthenticationInfo;
  76. import org.apache.maven.wagon.proxy.ProxyInfo;
  77. import org.apache.maven.wagon.repository.Repository;
  78. import org.apache.tools.ant.types.selectors.SelectorUtils;
  79. import org.slf4j.Logger;
  80. import org.slf4j.LoggerFactory;
  81. import org.slf4j.MarkerFactory;
  82. import org.springframework.stereotype.Service;
  83. import javax.annotation.PostConstruct;
  84. import javax.inject.Inject;
  85. import javax.inject.Named;
  86. import java.io.IOException;
  87. import java.nio.file.Files;
  88. import java.nio.file.Path;
  89. import java.nio.file.Paths;
  90. import java.util.ArrayList;
  91. import java.util.Collections;
  92. import java.util.LinkedHashMap;
  93. import java.util.List;
  94. import java.util.Map;
  95. import java.util.Map.Entry;
  96. import java.util.Properties;
  97. import java.util.concurrent.ConcurrentHashMap;
  98. import java.util.concurrent.ConcurrentMap;
  99. /**
  100. * DefaultRepositoryProxyConnectors
  101. * TODO exception handling needs work - "not modified" is not really an exceptional case, and it has more layers than
  102. * your average brown onion
  103. */
  104. @Service("repositoryProxyConnectors#default")
  105. public class DefaultRepositoryProxyConnectors
  106. implements RepositoryProxyConnectors, RegistryListener
  107. {
  108. private Logger log = LoggerFactory.getLogger( DefaultRepositoryProxyConnectors.class );
  109. @Inject
  110. @Named(value = "archivaConfiguration#default")
  111. private ArchivaConfiguration archivaConfiguration;
  112. @Inject
  113. @Named(value = "repositoryContentFactory#default")
  114. private RepositoryContentFactory repositoryFactory;
  115. @Inject
  116. @Named(value = "metadataTools#default")
  117. private MetadataTools metadataTools;
  118. @Inject
  119. private Map<String, PreDownloadPolicy> preDownloadPolicies;
  120. @Inject
  121. private Map<String, PostDownloadPolicy> postDownloadPolicies;
  122. @Inject
  123. private Map<String, DownloadErrorPolicy> downloadErrorPolicies;
  124. @Inject
  125. private UrlFailureCache urlFailureCache;
  126. private ConcurrentMap<String, List<ProxyConnector>> proxyConnectorMap = new ConcurrentHashMap<>();
  127. private ConcurrentMap<String, ProxyInfo> networkProxyMap = new ConcurrentHashMap<>();
  128. @Inject
  129. private WagonFactory wagonFactory;
  130. @Inject
  131. @Named(value = "archivaTaskScheduler#repository")
  132. private ArchivaTaskScheduler scheduler;
  133. @Inject
  134. private RepositoryRegistry repositoryRegistry;
  135. @Inject
  136. private NetworkProxyAdmin networkProxyAdmin;
  137. @Inject
  138. @Named(value = "fileLockManager#default")
  139. private FileLockManager fileLockManager;
  140. @PostConstruct
  141. public void initialize()
  142. {
  143. initConnectorsAndNetworkProxies();
  144. archivaConfiguration.addChangeListener( this );
  145. }
  146. @SuppressWarnings("unchecked")
  147. private void initConnectorsAndNetworkProxies()
  148. {
  149. ProxyConnectorOrderComparator proxyOrderSorter = new ProxyConnectorOrderComparator();
  150. this.proxyConnectorMap.clear();
  151. Configuration configuration = archivaConfiguration.getConfiguration();
  152. List<ProxyConnectorRuleConfiguration> allProxyConnectorRuleConfigurations =
  153. configuration.getProxyConnectorRuleConfigurations();
  154. List<ProxyConnectorConfiguration> proxyConfigs = configuration.getProxyConnectors();
  155. for ( ProxyConnectorConfiguration proxyConfig : proxyConfigs )
  156. {
  157. String key = proxyConfig.getSourceRepoId();
  158. // Create connector object.
  159. ProxyConnector connector = new ProxyConnector();
  160. ManagedRepository repo = repositoryRegistry.getManagedRepository( proxyConfig.getSourceRepoId( ) );
  161. if (repo==null) {
  162. log.error("Cannot find source repository after config change "+proxyConfig.getSourceRepoId());
  163. continue;
  164. }
  165. connector.setSourceRepository(repo.getContent());
  166. RemoteRepository rRepo = repositoryRegistry.getRemoteRepository( proxyConfig.getTargetRepoId() );
  167. if (rRepo==null) {
  168. log.error("Cannot find target repository after config change "+proxyConfig.getSourceRepoId());
  169. continue;
  170. }
  171. connector.setTargetRepository(rRepo.getContent());
  172. connector.setProxyId( proxyConfig.getProxyId() );
  173. connector.setPolicies( proxyConfig.getPolicies() );
  174. connector.setOrder( proxyConfig.getOrder() );
  175. connector.setDisabled( proxyConfig.isDisabled() );
  176. // Copy any blacklist patterns.
  177. List<String> blacklist = new ArrayList<>( 0 );
  178. if ( CollectionUtils.isNotEmpty( proxyConfig.getBlackListPatterns() ) )
  179. {
  180. blacklist.addAll( proxyConfig.getBlackListPatterns() );
  181. }
  182. connector.setBlacklist( blacklist );
  183. // Copy any whitelist patterns.
  184. List<String> whitelist = new ArrayList<>( 0 );
  185. if ( CollectionUtils.isNotEmpty( proxyConfig.getWhiteListPatterns() ) )
  186. {
  187. whitelist.addAll( proxyConfig.getWhiteListPatterns() );
  188. }
  189. connector.setWhitelist( whitelist );
  190. List<ProxyConnectorRuleConfiguration> proxyConnectorRuleConfigurations =
  191. findProxyConnectorRules( connector.getSourceRepository().getId(),
  192. connector.getTargetRepository().getId(),
  193. allProxyConnectorRuleConfigurations );
  194. if ( !proxyConnectorRuleConfigurations.isEmpty() )
  195. {
  196. for ( ProxyConnectorRuleConfiguration proxyConnectorRuleConfiguration : proxyConnectorRuleConfigurations )
  197. {
  198. if ( StringUtils.equals( proxyConnectorRuleConfiguration.getRuleType(),
  199. ProxyConnectorRuleType.BLACK_LIST.getRuleType() ) )
  200. {
  201. connector.getBlacklist().add( proxyConnectorRuleConfiguration.getPattern() );
  202. }
  203. if ( StringUtils.equals( proxyConnectorRuleConfiguration.getRuleType(),
  204. ProxyConnectorRuleType.WHITE_LIST.getRuleType() ) )
  205. {
  206. connector.getWhitelist().add( proxyConnectorRuleConfiguration.getPattern() );
  207. }
  208. }
  209. }
  210. // Get other connectors
  211. List<ProxyConnector> connectors = this.proxyConnectorMap.get( key );
  212. if ( connectors == null )
  213. {
  214. // Create if we are the first.
  215. connectors = new ArrayList<>( 1 );
  216. }
  217. // Add the connector.
  218. connectors.add( connector );
  219. // Ensure the list is sorted.
  220. Collections.sort( connectors, proxyOrderSorter );
  221. // Set the key to the list of connectors.
  222. this.proxyConnectorMap.put( key, connectors );
  223. }
  224. this.networkProxyMap.clear();
  225. List<NetworkProxyConfiguration> networkProxies = archivaConfiguration.getConfiguration().getNetworkProxies();
  226. for ( NetworkProxyConfiguration networkProxyConfig : networkProxies )
  227. {
  228. String key = networkProxyConfig.getId();
  229. ProxyInfo proxy = new ProxyInfo();
  230. proxy.setType( networkProxyConfig.getProtocol() );
  231. proxy.setHost( networkProxyConfig.getHost() );
  232. proxy.setPort( networkProxyConfig.getPort() );
  233. proxy.setUserName( networkProxyConfig.getUsername() );
  234. proxy.setPassword( networkProxyConfig.getPassword() );
  235. this.networkProxyMap.put( key, proxy );
  236. }
  237. }
  238. private List<ProxyConnectorRuleConfiguration> findProxyConnectorRules( String sourceRepository,
  239. String targetRepository,
  240. List<ProxyConnectorRuleConfiguration> all )
  241. {
  242. List<ProxyConnectorRuleConfiguration> proxyConnectorRuleConfigurations = new ArrayList<>();
  243. for ( ProxyConnectorRuleConfiguration proxyConnectorRuleConfiguration : all )
  244. {
  245. for ( ProxyConnectorConfiguration proxyConnector : proxyConnectorRuleConfiguration.getProxyConnectors() )
  246. {
  247. if ( StringUtils.equals( sourceRepository, proxyConnector.getSourceRepoId() ) && StringUtils.equals(
  248. targetRepository, proxyConnector.getTargetRepoId() ) )
  249. {
  250. proxyConnectorRuleConfigurations.add( proxyConnectorRuleConfiguration );
  251. }
  252. }
  253. }
  254. return proxyConnectorRuleConfigurations;
  255. }
  256. @Override
  257. public Path fetchFromProxies( ManagedRepositoryContent repository, ArtifactReference artifact )
  258. throws ProxyDownloadException
  259. {
  260. Path localFile = toLocalFile( repository, artifact );
  261. Properties requestProperties = new Properties();
  262. requestProperties.setProperty( "filetype", "artifact" );
  263. requestProperties.setProperty( "version", artifact.getVersion() );
  264. requestProperties.setProperty( "managedRepositoryId", repository.getId() );
  265. List<ProxyConnector> connectors = getProxyConnectors( repository );
  266. Map<String, Exception> previousExceptions = new LinkedHashMap<>();
  267. for ( ProxyConnector connector : connectors )
  268. {
  269. if ( connector.isDisabled() )
  270. {
  271. continue;
  272. }
  273. RemoteRepositoryContent targetRepository = connector.getTargetRepository();
  274. requestProperties.setProperty( "remoteRepositoryId", targetRepository.getId() );
  275. String targetPath = targetRepository.toPath( artifact );
  276. if ( SystemUtils.IS_OS_WINDOWS )
  277. {
  278. // toPath use system PATH_SEPARATOR so on windows url are \ which doesn't work very well :-)
  279. targetPath = FilenameUtils.separatorsToUnix( targetPath );
  280. }
  281. try
  282. {
  283. Path downloadedFile =
  284. transferFile( connector, targetRepository, targetPath, repository, localFile, requestProperties,
  285. true );
  286. if ( fileExists( downloadedFile ) )
  287. {
  288. log.debug( "Successfully transferred: {}", downloadedFile.toAbsolutePath() );
  289. return downloadedFile;
  290. }
  291. }
  292. catch ( NotFoundException e )
  293. {
  294. log.debug( "Artifact {} not found on repository \"{}\".", Keys.toKey( artifact ),
  295. targetRepository.getRepository().getId() );
  296. }
  297. catch ( NotModifiedException e )
  298. {
  299. log.debug( "Artifact {} not updated on repository \"{}\".", Keys.toKey( artifact ),
  300. targetRepository.getRepository().getId() );
  301. }
  302. catch ( ProxyException | RepositoryAdminException e )
  303. {
  304. validatePolicies( this.downloadErrorPolicies, connector.getPolicies(), requestProperties, artifact,
  305. targetRepository, localFile, e, previousExceptions );
  306. }
  307. }
  308. if ( !previousExceptions.isEmpty() )
  309. {
  310. throw new ProxyDownloadException( "Failures occurred downloading from some remote repositories",
  311. previousExceptions );
  312. }
  313. log.debug( "Exhausted all target repositories, artifact {} not found.", Keys.toKey( artifact ) );
  314. return null;
  315. }
  316. @Override
  317. public Path fetchFromProxies( ManagedRepositoryContent repository, String path )
  318. {
  319. Path localFile = Paths.get( repository.getRepoRoot(), path );
  320. // no update policies for these paths
  321. if ( Files.exists(localFile) )
  322. {
  323. return null;
  324. }
  325. Properties requestProperties = new Properties();
  326. requestProperties.setProperty( "filetype", "resource" );
  327. requestProperties.setProperty( "managedRepositoryId", repository.getId() );
  328. List<ProxyConnector> connectors = getProxyConnectors( repository );
  329. for ( ProxyConnector connector : connectors )
  330. {
  331. if ( connector.isDisabled() )
  332. {
  333. continue;
  334. }
  335. RemoteRepositoryContent targetRepository = connector.getTargetRepository();
  336. requestProperties.setProperty( "remoteRepositoryId", targetRepository.getId() );
  337. String targetPath = path;
  338. try
  339. {
  340. Path downloadedFile =
  341. transferFile( connector, targetRepository, targetPath, repository, localFile, requestProperties,
  342. false );
  343. if ( fileExists( downloadedFile ) )
  344. {
  345. log.debug( "Successfully transferred: {}", downloadedFile.toAbsolutePath() );
  346. return downloadedFile;
  347. }
  348. }
  349. catch ( NotFoundException e )
  350. {
  351. log.debug( "Resource {} not found on repository \"{}\".", path,
  352. targetRepository.getRepository().getId() );
  353. }
  354. catch ( NotModifiedException e )
  355. {
  356. log.debug( "Resource {} not updated on repository \"{}\".", path,
  357. targetRepository.getRepository().getId() );
  358. }
  359. catch ( ProxyException e )
  360. {
  361. log.warn(
  362. "Transfer error from repository {} for resource {}, continuing to next repository. Error message: {}",
  363. targetRepository.getRepository().getId(), path, e.getMessage() );
  364. log.debug( MarkerFactory.getDetachedMarker( "transfer.error" ),
  365. "Transfer error from repository \"{}"
  366. + "\" for resource {}, continuing to next repository. Error message: {}",
  367. targetRepository.getRepository().getId(), path, e.getMessage(), e );
  368. }
  369. catch ( RepositoryAdminException e )
  370. {
  371. log.debug( MarkerFactory.getDetachedMarker( "transfer.error" ),
  372. "Transfer error from repository {} for resource {}, continuing to next repository. Error message: {}",
  373. targetRepository.getRepository().getId(), path, e.getMessage(), e );
  374. log.debug( MarkerFactory.getDetachedMarker( "transfer.error" ), "Full stack trace", e );
  375. }
  376. }
  377. log.debug( "Exhausted all target repositories, resource {} not found.", path );
  378. return null;
  379. }
  380. @Override
  381. public ProxyFetchResult fetchMetadataFromProxies( ManagedRepositoryContent repository, String logicalPath )
  382. {
  383. Path localFile = Paths.get( repository.getRepoRoot(), logicalPath );
  384. Properties requestProperties = new Properties();
  385. requestProperties.setProperty( "filetype", "metadata" );
  386. boolean metadataNeedsUpdating = false;
  387. long originalTimestamp = getLastModified( localFile );
  388. List<ProxyConnector> connectors = new ArrayList<>( getProxyConnectors( repository ) );
  389. for ( ProxyConnector connector : connectors )
  390. {
  391. if ( connector.isDisabled() )
  392. {
  393. continue;
  394. }
  395. RemoteRepositoryContent targetRepository = connector.getTargetRepository();
  396. Path localRepoFile = toLocalRepoFile( repository, targetRepository, logicalPath );
  397. long originalMetadataTimestamp = getLastModified( localRepoFile );
  398. try
  399. {
  400. transferFile( connector, targetRepository, logicalPath, repository, localRepoFile, requestProperties,
  401. true );
  402. if ( hasBeenUpdated( localRepoFile, originalMetadataTimestamp ) )
  403. {
  404. metadataNeedsUpdating = true;
  405. }
  406. }
  407. catch ( NotFoundException e )
  408. {
  409. log.debug( "Metadata {} not found on remote repository '{}'.", logicalPath,
  410. targetRepository.getRepository().getId(), e );
  411. }
  412. catch ( NotModifiedException e )
  413. {
  414. log.debug( "Metadata {} not updated on remote repository '{}'.", logicalPath,
  415. targetRepository.getRepository().getId(), e );
  416. }
  417. catch ( ProxyException | RepositoryAdminException e )
  418. {
  419. log.warn(
  420. "Transfer error from repository {} for versioned Metadata {}, continuing to next repository. Error message: {}",
  421. targetRepository.getRepository().getId(), logicalPath, e.getMessage() );
  422. log.debug( "Full stack trace", e );
  423. }
  424. }
  425. if ( hasBeenUpdated( localFile, originalTimestamp ) )
  426. {
  427. metadataNeedsUpdating = true;
  428. }
  429. if ( metadataNeedsUpdating || !Files.exists(localFile))
  430. {
  431. try
  432. {
  433. metadataTools.updateMetadata( repository, logicalPath );
  434. }
  435. catch ( RepositoryMetadataException e )
  436. {
  437. log.warn( "Unable to update metadata {}:{}", localFile.toAbsolutePath(), e.getMessage(), e );
  438. }
  439. }
  440. if ( fileExists( localFile ) )
  441. {
  442. return new ProxyFetchResult( localFile, metadataNeedsUpdating );
  443. }
  444. return new ProxyFetchResult( null, false );
  445. }
  446. /**
  447. * @param connector
  448. * @param remoteRepository
  449. * @param tmpMd5
  450. * @param tmpSha1
  451. * @param tmpResource
  452. * @param url
  453. * @param remotePath
  454. * @param resource
  455. * @param workingDirectory
  456. * @param repository
  457. * @throws ProxyException
  458. * @throws NotModifiedException
  459. * @throws org.apache.archiva.admin.model.RepositoryAdminException
  460. */
  461. protected void transferResources( ProxyConnector connector, RemoteRepositoryContent remoteRepository, Path tmpMd5,
  462. Path tmpSha1, Path tmpResource, String url, String remotePath, Path resource,
  463. Path workingDirectory, ManagedRepositoryContent repository )
  464. throws ProxyException, NotModifiedException, RepositoryAdminException
  465. {
  466. Wagon wagon = null;
  467. try
  468. {
  469. RepositoryURL repoUrl = remoteRepository.getURL();
  470. String protocol = repoUrl.getProtocol();
  471. NetworkProxy networkProxy = null;
  472. if ( StringUtils.isNotBlank( connector.getProxyId() ) )
  473. {
  474. networkProxy = networkProxyAdmin.getNetworkProxy( connector.getProxyId() );
  475. }
  476. WagonFactoryRequest wagonFactoryRequest = new WagonFactoryRequest( "wagon#" + protocol,
  477. remoteRepository.getRepository().getExtraHeaders() ).networkProxy(
  478. networkProxy );
  479. wagon = wagonFactory.getWagon( wagonFactoryRequest );
  480. if ( wagon == null )
  481. {
  482. throw new ProxyException( "Unsupported target repository protocol: " + protocol );
  483. }
  484. if ( wagon == null )
  485. {
  486. throw new ProxyException( "Unsupported target repository protocol: " + protocol );
  487. }
  488. boolean connected = connectToRepository( connector, wagon, remoteRepository );
  489. if ( connected )
  490. {
  491. transferArtifact( wagon, remoteRepository, remotePath, repository, resource, workingDirectory,
  492. tmpResource );
  493. // TODO: these should be used to validate the download based on the policies, not always downloaded
  494. // to
  495. // save on connections since md5 is rarely used
  496. transferChecksum( wagon, remoteRepository, remotePath, repository, resource, workingDirectory, ".sha1",
  497. tmpSha1 );
  498. transferChecksum( wagon, remoteRepository, remotePath, repository, resource, workingDirectory, ".md5",
  499. tmpMd5 );
  500. }
  501. }
  502. catch ( NotFoundException e )
  503. {
  504. urlFailureCache.cacheFailure( url );
  505. throw e;
  506. }
  507. catch ( NotModifiedException e )
  508. {
  509. // Do not cache url here.
  510. throw e;
  511. }
  512. catch ( ProxyException e )
  513. {
  514. urlFailureCache.cacheFailure( url );
  515. throw e;
  516. }
  517. catch ( WagonFactoryException e )
  518. {
  519. throw new ProxyException( e.getMessage(), e );
  520. }
  521. finally
  522. {
  523. if ( wagon != null )
  524. {
  525. try
  526. {
  527. wagon.disconnect();
  528. }
  529. catch ( ConnectionException e )
  530. {
  531. log.warn( "Unable to disconnect wagon.", e );
  532. }
  533. }
  534. }
  535. }
  536. private void transferArtifact( Wagon wagon, RemoteRepositoryContent remoteRepository, String remotePath,
  537. ManagedRepositoryContent repository, Path resource, Path tmpDirectory,
  538. Path destFile )
  539. throws ProxyException
  540. {
  541. transferSimpleFile( wagon, remoteRepository, remotePath, repository, resource, destFile );
  542. }
  543. private long getLastModified( Path file )
  544. {
  545. if ( !Files.exists(file) || !Files.isRegularFile(file) )
  546. {
  547. return 0;
  548. }
  549. try
  550. {
  551. return Files.getLastModifiedTime(file).toMillis();
  552. }
  553. catch ( IOException e )
  554. {
  555. log.error("Could get the modified time of file {}", file.toAbsolutePath());
  556. return 0;
  557. }
  558. }
  559. private boolean hasBeenUpdated( Path file, long originalLastModified )
  560. {
  561. if ( !Files.exists(file) || !Files.isRegularFile(file) )
  562. {
  563. return false;
  564. }
  565. long currentLastModified = getLastModified( file );
  566. return ( currentLastModified > originalLastModified );
  567. }
  568. private Path toLocalRepoFile( ManagedRepositoryContent repository, RemoteRepositoryContent targetRepository,
  569. String targetPath )
  570. {
  571. String repoPath = metadataTools.getRepositorySpecificName( targetRepository, targetPath );
  572. return Paths.get( repository.getRepoRoot(), repoPath );
  573. }
  574. /**
  575. * Test if the provided ManagedRepositoryContent has any proxies configured for it.
  576. */
  577. @Override
  578. public boolean hasProxies( ManagedRepositoryContent repository )
  579. {
  580. synchronized ( this.proxyConnectorMap )
  581. {
  582. return this.proxyConnectorMap.containsKey( repository.getId() );
  583. }
  584. }
  585. private Path toLocalFile( ManagedRepositoryContent repository, ArtifactReference artifact )
  586. {
  587. return repository.toFile( artifact );
  588. }
  589. /**
  590. * Simple method to test if the file exists on the local disk.
  591. *
  592. * @param file the file to test. (may be null)
  593. * @return true if file exists. false if the file param is null, doesn't exist, or is not of type File.
  594. */
  595. private boolean fileExists( Path file )
  596. {
  597. if ( file == null )
  598. {
  599. return false;
  600. }
  601. if ( !Files.exists(file))
  602. {
  603. return false;
  604. }
  605. return Files.isRegularFile(file);
  606. }
  607. /**
  608. * Perform the transfer of the file.
  609. *
  610. * @param connector the connector configuration to use.
  611. * @param remoteRepository the remote repository get the resource from.
  612. * @param remotePath the path in the remote repository to the resource to get.
  613. * @param repository the managed repository that will hold the file
  614. * @param resource the local file to place the downloaded resource into
  615. * @param requestProperties the request properties to utilize for policy handling.
  616. * @param executeConsumers whether to execute the consumers after proxying
  617. * @return the local file that was downloaded, or null if not downloaded.
  618. * @throws NotFoundException if the file was not found on the remote repository.
  619. * @throws NotModifiedException if the localFile was present, and the resource was present on remote repository, but
  620. * the remote resource is not newer than the local File.
  621. * @throws ProxyException if transfer was unsuccessful.
  622. */
  623. private Path transferFile( ProxyConnector connector, RemoteRepositoryContent remoteRepository, String remotePath,
  624. ManagedRepositoryContent repository, Path resource, Properties requestProperties,
  625. boolean executeConsumers )
  626. throws ProxyException, NotModifiedException, RepositoryAdminException
  627. {
  628. String url = remoteRepository.getURL().getUrl();
  629. if ( !url.endsWith( "/" ) )
  630. {
  631. url = url + "/";
  632. }
  633. url = url + remotePath;
  634. requestProperties.setProperty( "url", url );
  635. // Is a whitelist defined?
  636. if ( CollectionUtils.isNotEmpty( connector.getWhitelist() ) )
  637. {
  638. // Path must belong to whitelist.
  639. if ( !matchesPattern( remotePath, connector.getWhitelist() ) )
  640. {
  641. log.debug( "Path [{}] is not part of defined whitelist (skipping transfer from repository [{}]).",
  642. remotePath, remoteRepository.getRepository().getName() );
  643. return null;
  644. }
  645. }
  646. // Is target path part of blacklist?
  647. if ( matchesPattern( remotePath, connector.getBlacklist() ) )
  648. {
  649. log.debug( "Path [{}] is part of blacklist (skipping transfer from repository [{}]).", remotePath,
  650. remoteRepository.getRepository().getName() );
  651. return null;
  652. }
  653. // Handle pre-download policy
  654. try
  655. {
  656. validatePolicies( this.preDownloadPolicies, connector.getPolicies(), requestProperties, resource );
  657. }
  658. catch ( PolicyViolationException e )
  659. {
  660. String emsg = "Transfer not attempted on " + url + " : " + e.getMessage();
  661. if ( fileExists( resource ) )
  662. {
  663. log.debug( "{} : using already present local file.", emsg );
  664. return resource;
  665. }
  666. log.debug( emsg );
  667. return null;
  668. }
  669. Path workingDirectory = createWorkingDirectory( repository );
  670. Path tmpResource = workingDirectory.resolve(resource.getFileName());
  671. Path tmpMd5 = workingDirectory.resolve(resource.getFileName().toString() + ".md5" );
  672. Path tmpSha1 = workingDirectory.resolve( resource.getFileName().toString() + ".sha1" );
  673. try
  674. {
  675. transferResources( connector, remoteRepository, tmpMd5, tmpSha1, tmpResource, url, remotePath, resource,
  676. workingDirectory, repository );
  677. // Handle post-download policies.
  678. try
  679. {
  680. validatePolicies( this.postDownloadPolicies, connector.getPolicies(), requestProperties, tmpResource );
  681. }
  682. catch ( PolicyViolationException e )
  683. {
  684. log.warn( "Transfer invalidated from {} : {}", url, e.getMessage() );
  685. executeConsumers = false;
  686. if ( !fileExists( tmpResource ) )
  687. {
  688. resource = null;
  689. }
  690. }
  691. if ( resource != null )
  692. {
  693. synchronized ( resource.toAbsolutePath().toString().intern() )
  694. {
  695. Path directory = resource.getParent();
  696. moveFileIfExists( tmpMd5, directory );
  697. moveFileIfExists( tmpSha1, directory );
  698. moveFileIfExists( tmpResource, directory );
  699. }
  700. }
  701. }
  702. finally
  703. {
  704. org.apache.archiva.common.utils.FileUtils.deleteQuietly( workingDirectory );
  705. }
  706. if ( executeConsumers )
  707. {
  708. // Just-in-time update of the index and database by executing the consumers for this artifact
  709. //consumers.executeConsumers( connector.getSourceRepository().getRepository(), resource );
  710. queueRepositoryTask( connector.getSourceRepository().getRepository().getId(), resource );
  711. }
  712. return resource;
  713. }
  714. private void queueRepositoryTask( String repositoryId, Path localFile )
  715. {
  716. RepositoryTask task = new RepositoryTask();
  717. task.setRepositoryId( repositoryId );
  718. task.setResourceFile( localFile );
  719. task.setUpdateRelatedArtifacts( true );
  720. task.setScanAll( true );
  721. try
  722. {
  723. scheduler.queueTask( task );
  724. }
  725. catch ( TaskQueueException e )
  726. {
  727. log.error( "Unable to queue repository task to execute consumers on resource file ['{}"
  728. + "'].", localFile.getFileName() );
  729. }
  730. }
  731. /**
  732. * Moves the file into repository location if it exists
  733. *
  734. * @param fileToMove this could be either the main artifact, sha1 or md5 checksum file.
  735. * @param directory directory to write files to
  736. */
  737. private void moveFileIfExists( Path fileToMove, Path directory )
  738. throws ProxyException
  739. {
  740. if ( fileToMove != null && Files.exists(fileToMove) )
  741. {
  742. Path newLocation = directory.resolve(fileToMove.getFileName());
  743. moveTempToTarget( fileToMove, newLocation );
  744. }
  745. }
  746. /**
  747. * <p>
  748. * Quietly transfer the checksum file from the remote repository to the local file.
  749. * </p>
  750. *
  751. * @param wagon the wagon instance (should already be connected) to use.
  752. * @param remoteRepository the remote repository to transfer from.
  753. * @param remotePath the remote path to the resource to get.
  754. * @param repository the managed repository that will hold the file
  755. * @param resource the local file that should contain the downloaded contents
  756. * @param tmpDirectory the temporary directory to download to
  757. * @param ext the type of checksum to transfer (example: ".md5" or ".sha1")
  758. * @throws ProxyException if copying the downloaded file into place did not succeed.
  759. */
  760. private void transferChecksum( Wagon wagon, RemoteRepositoryContent remoteRepository, String remotePath,
  761. ManagedRepositoryContent repository, Path resource, Path tmpDirectory, String ext,
  762. Path destFile )
  763. throws ProxyException
  764. {
  765. String url = remoteRepository.getURL().getUrl() + remotePath + ext;
  766. // Transfer checksum does not use the policy.
  767. if ( urlFailureCache.hasFailedBefore( url ) )
  768. {
  769. return;
  770. }
  771. try
  772. {
  773. transferSimpleFile( wagon, remoteRepository, remotePath + ext, repository, resource, destFile );
  774. log.debug( "Checksum {} Downloaded: {} to move to {}", url, destFile, resource );
  775. }
  776. catch ( NotFoundException e )
  777. {
  778. urlFailureCache.cacheFailure( url );
  779. log.debug( "Transfer failed, checksum not found: {}", url );
  780. // Consume it, do not pass this on.
  781. }
  782. catch ( NotModifiedException e )
  783. {
  784. log.debug( "Transfer skipped, checksum not modified: {}", url );
  785. // Consume it, do not pass this on.
  786. }
  787. catch ( ProxyException e )
  788. {
  789. urlFailureCache.cacheFailure( url );
  790. log.warn( "Transfer failed on checksum: {} : {}", url, e.getMessage(), e );
  791. // Critical issue, pass it on.
  792. throw e;
  793. }
  794. }
  795. /**
  796. * Perform the transfer of the remote file to the local file specified.
  797. *
  798. * @param wagon the wagon instance to use.
  799. * @param remoteRepository the remote repository to use
  800. * @param remotePath the remote path to attempt to get
  801. * @param repository the managed repository that will hold the file
  802. * @param origFile the local file to save to
  803. * @throws ProxyException if there was a problem moving the downloaded file into place.
  804. */
  805. private void transferSimpleFile( Wagon wagon, RemoteRepositoryContent remoteRepository, String remotePath,
  806. ManagedRepositoryContent repository, Path origFile, Path destFile )
  807. throws ProxyException
  808. {
  809. assert ( remotePath != null );
  810. // Transfer the file.
  811. try
  812. {
  813. boolean success = false;
  814. if ( !Files.exists(origFile))
  815. {
  816. log.debug( "Retrieving {} from {}", remotePath, remoteRepository.getRepository().getName() );
  817. wagon.get( addParameters( remotePath, remoteRepository.getRepository() ), destFile.toFile() );
  818. success = true;
  819. // You wouldn't get here on failure, a WagonException would have been thrown.
  820. log.debug( "Downloaded successfully." );
  821. }
  822. else
  823. {
  824. log.debug( "Retrieving {} from {} if updated", remotePath, remoteRepository.getRepository().getName() );
  825. try
  826. {
  827. success = wagon.getIfNewer( addParameters( remotePath, remoteRepository.getRepository() ), destFile.toFile(),
  828. Files.getLastModifiedTime(origFile).toMillis());
  829. }
  830. catch ( IOException e )
  831. {
  832. throw new ProxyException( "Failed to the modification time of "+origFile.toAbsolutePath() );
  833. }
  834. if ( !success )
  835. {
  836. throw new NotModifiedException(
  837. "Not downloaded, as local file is newer than remote side: " + origFile.toAbsolutePath() );
  838. }
  839. if ( Files.exists(destFile))
  840. {
  841. log.debug( "Downloaded successfully." );
  842. }
  843. }
  844. }
  845. catch ( ResourceDoesNotExistException e )
  846. {
  847. throw new NotFoundException(
  848. "Resource [" + remoteRepository.getURL() + "/" + remotePath + "] does not exist: " + e.getMessage(),
  849. e );
  850. }
  851. catch ( WagonException e )
  852. {
  853. // TODO: shouldn't have to drill into the cause, but TransferFailedException is often not descriptive enough
  854. String msg =
  855. "Download failure on resource [" + remoteRepository.getURL() + "/" + remotePath + "]:" + e.getMessage();
  856. if ( e.getCause() != null )
  857. {
  858. msg += " (cause: " + e.getCause() + ")";
  859. }
  860. throw new ProxyException( msg, e );
  861. }
  862. }
  863. /**
  864. * Apply the policies.
  865. *
  866. * @param policies the map of policies to execute. (Map of String policy keys, to {@link DownloadPolicy} objects)
  867. * @param settings the map of settings for the policies to execute. (Map of String policy keys, to String policy
  868. * setting)
  869. * @param request the request properties (utilized by the {@link DownloadPolicy#applyPolicy(String, Properties, Path)}
  870. * )
  871. * @param localFile the local file (utilized by the {@link DownloadPolicy#applyPolicy(String, Properties, Path)})
  872. * @throws PolicyViolationException
  873. */
  874. private void validatePolicies( Map<String, ? extends DownloadPolicy> policies, Map<String, String> settings,
  875. Properties request, Path localFile )
  876. throws PolicyViolationException
  877. {
  878. for ( Entry<String, ? extends DownloadPolicy> entry : policies.entrySet() )
  879. {
  880. // olamy with spring rolehint is now downloadPolicy#hint
  881. // so substring after last # to get the hint as with plexus
  882. String key = StringUtils.substringAfterLast( entry.getKey(), "#" );
  883. DownloadPolicy policy = entry.getValue();
  884. String defaultSetting = policy.getDefaultOption();
  885. String setting = StringUtils.defaultString( settings.get( key ), defaultSetting );
  886. log.debug( "Applying [{}] policy with [{}]", key, setting );
  887. try
  888. {
  889. policy.applyPolicy( setting, request, localFile );
  890. }
  891. catch ( PolicyConfigurationException e )
  892. {
  893. log.error( e.getMessage(), e );
  894. }
  895. }
  896. }
  897. private void validatePolicies( Map<String, DownloadErrorPolicy> policies, Map<String, String> settings,
  898. Properties request, ArtifactReference artifact, RemoteRepositoryContent content,
  899. Path localFile, Exception exception, Map<String, Exception> previousExceptions )
  900. throws ProxyDownloadException
  901. {
  902. boolean process = true;
  903. for ( Entry<String, ? extends DownloadErrorPolicy> entry : policies.entrySet() )
  904. {
  905. // olamy with spring rolehint is now downloadPolicy#hint
  906. // so substring after last # to get the hint as with plexus
  907. String key = StringUtils.substringAfterLast( entry.getKey(), "#" );
  908. DownloadErrorPolicy policy = entry.getValue();
  909. String defaultSetting = policy.getDefaultOption();
  910. String setting = StringUtils.defaultString( settings.get( key ), defaultSetting );
  911. log.debug( "Applying [{}] policy with [{}]", key, setting );
  912. try
  913. {
  914. // all policies must approve the exception, any can cancel
  915. process = policy.applyPolicy( setting, request, localFile, exception, previousExceptions );
  916. if ( !process )
  917. {
  918. break;
  919. }
  920. }
  921. catch ( PolicyConfigurationException e )
  922. {
  923. log.error( e.getMessage(), e );
  924. }
  925. }
  926. if ( process )
  927. {
  928. // if the exception was queued, don't throw it
  929. if ( !previousExceptions.containsKey( content.getId() ) )
  930. {
  931. throw new ProxyDownloadException(
  932. "An error occurred in downloading from the remote repository, and the policy is to fail immediately",
  933. content.getId(), exception );
  934. }
  935. }
  936. else
  937. {
  938. // if the exception was queued, but cancelled, remove it
  939. previousExceptions.remove( content.getId() );
  940. }
  941. log.warn(
  942. "Transfer error from repository {} for artifact {} , continuing to next repository. Error message: {}",
  943. content.getRepository().getId(), Keys.toKey( artifact ), exception.getMessage() );
  944. log.debug( "Full stack trace", exception );
  945. }
  946. /**
  947. * Creates a working directory
  948. *
  949. * @param repository
  950. * @return file location of working directory
  951. */
  952. private Path createWorkingDirectory( ManagedRepositoryContent repository )
  953. {
  954. try
  955. {
  956. return Files.createTempDirectory( "temp" );
  957. }
  958. catch ( IOException e )
  959. {
  960. throw new RuntimeException( e.getMessage(), e );
  961. }
  962. }
  963. /**
  964. * Used to move the temporary file to its real destination. This is patterned from the way WagonManager handles its
  965. * downloaded files.
  966. *
  967. * @param temp The completed download file
  968. * @param target The final location of the downloaded file
  969. * @throws ProxyException when the temp file cannot replace the target file
  970. */
  971. private void moveTempToTarget( Path temp, Path target )
  972. throws ProxyException
  973. {
  974. Lock lock;
  975. try
  976. {
  977. lock = fileLockManager.writeFileLock( target );
  978. try {
  979. Files.deleteIfExists(lock.getFile());
  980. } catch (IOException e) {
  981. throw new ProxyException( "Unable to overwrite existing target file: " + target.toAbsolutePath() );
  982. }
  983. try {
  984. Files.createDirectories(lock.getFile().getParent());
  985. } catch (IOException e) {
  986. throw new ProxyException("Unable to create parent directory "+lock.getFile().getParent());
  987. }
  988. try
  989. {
  990. Files.move(temp, lock.getFile() );
  991. }
  992. catch ( IOException e )
  993. {
  994. log.warn( "Unable to rename tmp file to its final name... resorting to copy command." );
  995. try
  996. {
  997. Files.copy( temp, lock.getFile());
  998. }
  999. catch ( IOException e2 )
  1000. {
  1001. if ( Files.exists(lock.getFile()) )
  1002. {
  1003. log.debug( "Tried to copy file {} to {} but file with this name already exists.",
  1004. temp.getFileName(), lock.getFile().toAbsolutePath() );
  1005. }
  1006. else
  1007. {
  1008. throw new ProxyException(
  1009. "Cannot copy tmp file " + temp.toAbsolutePath() + " to its final location", e2 );
  1010. }
  1011. }
  1012. finally
  1013. {
  1014. org.apache.archiva.common.utils.FileUtils.deleteQuietly( temp );
  1015. }
  1016. }
  1017. }
  1018. catch ( FileLockException | FileLockTimeoutException e )
  1019. {
  1020. throw new ProxyException( e.getMessage(), e );
  1021. }
  1022. }
  1023. /**
  1024. * Using wagon, connect to the remote repository.
  1025. *
  1026. * @param connector the connector configuration to utilize (for obtaining network proxy configuration from)
  1027. * @param wagon the wagon instance to establish the connection on.
  1028. * @param remoteRepository the remote repository to connect to.
  1029. * @return true if the connection was successful. false if not connected.
  1030. */
  1031. private boolean connectToRepository( ProxyConnector connector, Wagon wagon,
  1032. RemoteRepositoryContent remoteRepository )
  1033. {
  1034. boolean connected = false;
  1035. final ProxyInfo networkProxy =
  1036. connector.getProxyId() == null ? null : this.networkProxyMap.get( connector.getProxyId() );
  1037. if ( log.isDebugEnabled() )
  1038. {
  1039. if ( networkProxy != null )
  1040. {
  1041. // TODO: move to proxyInfo.toString()
  1042. String msg = "Using network proxy " + networkProxy.getHost() + ":" + networkProxy.getPort()
  1043. + " to connect to remote repository " + remoteRepository.getURL();
  1044. if ( networkProxy.getNonProxyHosts() != null )
  1045. {
  1046. msg += "; excluding hosts: " + networkProxy.getNonProxyHosts();
  1047. }
  1048. if ( StringUtils.isNotBlank( networkProxy.getUserName() ) )
  1049. {
  1050. msg += "; as user: " + networkProxy.getUserName();
  1051. }
  1052. log.debug( msg );
  1053. }
  1054. }
  1055. AuthenticationInfo authInfo = null;
  1056. String username = "";
  1057. String password = "";
  1058. RepositoryCredentials repCred = remoteRepository.getRepository().getLoginCredentials();
  1059. if (repCred!=null && repCred instanceof PasswordCredentials) {
  1060. PasswordCredentials pwdCred = (PasswordCredentials) repCred;
  1061. username = pwdCred.getUsername();
  1062. password = pwdCred.getPassword()==null ? "" : new String(pwdCred.getPassword());
  1063. }
  1064. if ( StringUtils.isNotBlank( username ) && StringUtils.isNotBlank( password ) )
  1065. {
  1066. log.debug( "Using username {} to connect to remote repository {}", username, remoteRepository.getURL() );
  1067. authInfo = new AuthenticationInfo();
  1068. authInfo.setUserName( username );
  1069. authInfo.setPassword( password );
  1070. }
  1071. // Convert seconds to milliseconds
  1072. long timeoutInMilliseconds = remoteRepository.getRepository().getTimeout().toMillis();
  1073. // Set timeout read and connect
  1074. // FIXME olamy having 2 config values
  1075. wagon.setReadTimeout( (int) timeoutInMilliseconds );
  1076. wagon.setTimeout( (int) timeoutInMilliseconds );
  1077. try
  1078. {
  1079. Repository wagonRepository =
  1080. new Repository( remoteRepository.getId(), remoteRepository.getURL().toString() );
  1081. wagon.connect( wagonRepository, authInfo, networkProxy );
  1082. connected = true;
  1083. }
  1084. catch ( ConnectionException | AuthenticationException e )
  1085. {
  1086. log.warn( "Could not connect to {}: {}", remoteRepository.getRepository().getName(), e.getMessage() );
  1087. connected = false;
  1088. }
  1089. return connected;
  1090. }
  1091. /**
  1092. * Tests whitelist and blacklist patterns against path.
  1093. *
  1094. * @param path the path to test.
  1095. * @param patterns the list of patterns to check.
  1096. * @return true if the path matches at least 1 pattern in the provided patterns list.
  1097. */
  1098. private boolean matchesPattern( String path, List<String> patterns )
  1099. {
  1100. if ( CollectionUtils.isEmpty( patterns ) )
  1101. {
  1102. return false;
  1103. }
  1104. if ( !path.startsWith( "/" ) )
  1105. {
  1106. path = "/" + path;
  1107. }
  1108. for ( String pattern : patterns )
  1109. {
  1110. if ( !pattern.startsWith( "/" ) )
  1111. {
  1112. pattern = "/" + pattern;
  1113. }
  1114. if ( SelectorUtils.matchPath( pattern, path, false ) )
  1115. {
  1116. return true;
  1117. }
  1118. }
  1119. return false;
  1120. }
  1121. /**
  1122. * TODO: Ensure that list is correctly ordered based on configuration. See MRM-477
  1123. */
  1124. @Override
  1125. public List<ProxyConnector> getProxyConnectors( ManagedRepositoryContent repository )
  1126. {
  1127. if ( !this.proxyConnectorMap.containsKey( repository.getId() ) )
  1128. {
  1129. return Collections.emptyList();
  1130. }
  1131. List<ProxyConnector> ret = new ArrayList<>( this.proxyConnectorMap.get( repository.getId() ) );
  1132. Collections.sort( ret, ProxyConnectorOrderComparator.getInstance() );
  1133. return ret;
  1134. }
  1135. @Override
  1136. public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
  1137. {
  1138. if ( ConfigurationNames.isNetworkProxy( propertyName ) //
  1139. || ConfigurationNames.isManagedRepositories( propertyName ) //
  1140. || ConfigurationNames.isRemoteRepositories( propertyName ) //
  1141. || ConfigurationNames.isProxyConnector( propertyName ) ) //
  1142. {
  1143. initConnectorsAndNetworkProxies();
  1144. }
  1145. }
  1146. protected String addParameters( String path, RemoteRepository remoteRepository )
  1147. {
  1148. if ( remoteRepository.getExtraParameters().isEmpty() )
  1149. {
  1150. return path;
  1151. }
  1152. boolean question = false;
  1153. StringBuilder res = new StringBuilder( path == null ? "" : path );
  1154. for ( Entry<String, String> entry : remoteRepository.getExtraParameters().entrySet() )
  1155. {
  1156. if ( !question )
  1157. {
  1158. res.append( '?' ).append( entry.getKey() ).append( '=' ).append( entry.getValue() );
  1159. }
  1160. }
  1161. return res.toString();
  1162. }
  1163. @Override
  1164. public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
  1165. {
  1166. /* do nothing */
  1167. }
  1168. public ArchivaConfiguration getArchivaConfiguration()
  1169. {
  1170. return archivaConfiguration;
  1171. }
  1172. public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration )
  1173. {
  1174. this.archivaConfiguration = archivaConfiguration;
  1175. }
  1176. public RepositoryContentFactory getRepositoryFactory()
  1177. {
  1178. return repositoryFactory;
  1179. }
  1180. public void setRepositoryFactory( RepositoryContentFactory repositoryFactory )
  1181. {
  1182. this.repositoryFactory = repositoryFactory;
  1183. }
  1184. public MetadataTools getMetadataTools()
  1185. {
  1186. return metadataTools;
  1187. }
  1188. public void setMetadataTools( MetadataTools metadataTools )
  1189. {
  1190. this.metadataTools = metadataTools;
  1191. }
  1192. public UrlFailureCache getUrlFailureCache()
  1193. {
  1194. return urlFailureCache;
  1195. }
  1196. public void setUrlFailureCache( UrlFailureCache urlFailureCache )
  1197. {
  1198. this.urlFailureCache = urlFailureCache;
  1199. }
  1200. public WagonFactory getWagonFactory()
  1201. {
  1202. return wagonFactory;
  1203. }
  1204. public void setWagonFactory( WagonFactory wagonFactory )
  1205. {
  1206. this.wagonFactory = wagonFactory;
  1207. }
  1208. public Map<String, PreDownloadPolicy> getPreDownloadPolicies()
  1209. {
  1210. return preDownloadPolicies;
  1211. }
  1212. public void setPreDownloadPolicies( Map<String, PreDownloadPolicy> preDownloadPolicies )
  1213. {
  1214. this.preDownloadPolicies = preDownloadPolicies;
  1215. }
  1216. public Map<String, PostDownloadPolicy> getPostDownloadPolicies()
  1217. {
  1218. return postDownloadPolicies;
  1219. }
  1220. public void setPostDownloadPolicies( Map<String, PostDownloadPolicy> postDownloadPolicies )
  1221. {
  1222. this.postDownloadPolicies = postDownloadPolicies;
  1223. }
  1224. public Map<String, DownloadErrorPolicy> getDownloadErrorPolicies()
  1225. {
  1226. return downloadErrorPolicies;
  1227. }
  1228. public void setDownloadErrorPolicies( Map<String, DownloadErrorPolicy> downloadErrorPolicies )
  1229. {
  1230. this.downloadErrorPolicies = downloadErrorPolicies;
  1231. }
  1232. }