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 52KB

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