Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

DefaultRepositoryProxyConnectors.java 53KB

6 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
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. }