package org.apache.archiva.proxy;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import org.apache.archiva.admin.model.RepositoryAdminException;
import org.apache.archiva.admin.model.beans.NetworkProxy;
import org.apache.archiva.admin.model.beans.ProxyConnectorRuleType;
import org.apache.archiva.admin.model.beans.RemoteRepository;
import org.apache.archiva.admin.model.networkproxy.NetworkProxyAdmin;
import org.apache.archiva.common.filelock.FileLockException;
import org.apache.archiva.common.filelock.FileLockManager;
import org.apache.archiva.common.filelock.FileLockTimeoutException;
import org.apache.archiva.common.filelock.Lock;
import org.apache.archiva.configuration.ArchivaConfiguration;
import org.apache.archiva.configuration.Configuration;
import org.apache.archiva.configuration.ConfigurationNames;
import org.apache.archiva.configuration.NetworkProxyConfiguration;
import org.apache.archiva.configuration.ProxyConnectorConfiguration;
import org.apache.archiva.configuration.ProxyConnectorRuleConfiguration;
import org.apache.archiva.model.ArtifactReference;
import org.apache.archiva.model.Keys;
import org.apache.archiva.model.RepositoryURL;
import org.apache.archiva.policies.DownloadErrorPolicy;
import org.apache.archiva.policies.DownloadPolicy;
import org.apache.archiva.policies.PolicyConfigurationException;
import org.apache.archiva.policies.PolicyViolationException;
import org.apache.archiva.policies.PostDownloadPolicy;
import org.apache.archiva.policies.PreDownloadPolicy;
import org.apache.archiva.policies.ProxyDownloadException;
import org.apache.archiva.policies.urlcache.UrlFailureCache;
import org.apache.archiva.proxy.common.WagonFactory;
import org.apache.archiva.proxy.common.WagonFactoryException;
import org.apache.archiva.proxy.common.WagonFactoryRequest;
import org.apache.archiva.proxy.model.ProxyFetchResult;
import org.apache.archiva.proxy.model.ProxyConnector;
import org.apache.archiva.proxy.model.RepositoryProxyConnectors;
import org.apache.archiva.redback.components.registry.Registry;
import org.apache.archiva.redback.components.registry.RegistryListener;
import org.apache.archiva.redback.components.taskqueue.TaskQueueException;
import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.RemoteRepositoryContent;
import org.apache.archiva.repository.RepositoryContentFactory;
import org.apache.archiva.repository.RepositoryException;
import org.apache.archiva.repository.RepositoryNotFoundException;
import org.apache.archiva.repository.metadata.MetadataTools;
import org.apache.archiva.repository.metadata.RepositoryMetadataException;
import org.apache.archiva.scheduler.ArchivaTaskScheduler;
import org.apache.archiva.scheduler.repository.model.RepositoryTask;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.apache.maven.wagon.ConnectionException;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.Wagon;
import org.apache.maven.wagon.WagonException;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authentication.AuthenticationInfo;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.apache.maven.wagon.repository.Repository;
import org.apache.tools.ant.types.selectors.SelectorUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MarkerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * DefaultRepositoryProxyConnectors
 * TODO exception handling needs work - "not modified" is not really an exceptional case, and it has more layers than
 * your average brown onion
 */
@Service("repositoryProxyConnectors#default")
public class DefaultRepositoryProxyConnectors
    implements RepositoryProxyConnectors, RegistryListener
{
    private Logger log = LoggerFactory.getLogger( DefaultRepositoryProxyConnectors.class );

    @Inject
    @Named(value = "archivaConfiguration#default")
    private ArchivaConfiguration archivaConfiguration;

    @Inject
    @Named(value = "repositoryContentFactory#default")
    private RepositoryContentFactory repositoryFactory;

    @Inject
    @Named(value = "metadataTools#default")
    private MetadataTools metadataTools;

    @Inject
    private Map<String, PreDownloadPolicy> preDownloadPolicies;

    @Inject
    private Map<String, PostDownloadPolicy> postDownloadPolicies;

    @Inject
    private Map<String, DownloadErrorPolicy> downloadErrorPolicies;

    @Inject
    private UrlFailureCache urlFailureCache;

    private ConcurrentMap<String, List<ProxyConnector>> proxyConnectorMap = new ConcurrentHashMap<>();

    private ConcurrentMap<String, ProxyInfo> networkProxyMap = new ConcurrentHashMap<>();

    @Inject
    private WagonFactory wagonFactory;

    @Inject
    @Named(value = "archivaTaskScheduler#repository")
    private ArchivaTaskScheduler scheduler;

    @Inject
    private NetworkProxyAdmin networkProxyAdmin;

    @Inject
    @Named(value = "fileLockManager#default")
    private FileLockManager fileLockManager;

    @PostConstruct
    public void initialize()
    {
        initConnectorsAndNetworkProxies();
        archivaConfiguration.addChangeListener( this );

    }

    @SuppressWarnings("unchecked")
    private void initConnectorsAndNetworkProxies()
    {

        ProxyConnectorOrderComparator proxyOrderSorter = new ProxyConnectorOrderComparator();
        this.proxyConnectorMap.clear();

        Configuration configuration = archivaConfiguration.getConfiguration();

        List<ProxyConnectorRuleConfiguration> allProxyConnectorRuleConfigurations =
            configuration.getProxyConnectorRuleConfigurations();

        List<ProxyConnectorConfiguration> proxyConfigs = configuration.getProxyConnectors();
        for ( ProxyConnectorConfiguration proxyConfig : proxyConfigs )
        {
            String key = proxyConfig.getSourceRepoId();

            try
            {
                // Create connector object.
                ProxyConnector connector = new ProxyConnector();

                connector.setSourceRepository(
                    repositoryFactory.getManagedRepositoryContent( proxyConfig.getSourceRepoId() ) );
                connector.setTargetRepository(
                    repositoryFactory.getRemoteRepositoryContent( proxyConfig.getTargetRepoId() ) );

                connector.setProxyId( proxyConfig.getProxyId() );
                connector.setPolicies( proxyConfig.getPolicies() );
                connector.setOrder( proxyConfig.getOrder() );
                connector.setDisabled( proxyConfig.isDisabled() );

                // Copy any blacklist patterns.
                List<String> blacklist = new ArrayList<>( 0 );
                if ( CollectionUtils.isNotEmpty( proxyConfig.getBlackListPatterns() ) )
                {
                    blacklist.addAll( proxyConfig.getBlackListPatterns() );
                }
                connector.setBlacklist( blacklist );

                // Copy any whitelist patterns.
                List<String> whitelist = new ArrayList<>( 0 );
                if ( CollectionUtils.isNotEmpty( proxyConfig.getWhiteListPatterns() ) )
                {
                    whitelist.addAll( proxyConfig.getWhiteListPatterns() );
                }
                connector.setWhitelist( whitelist );

                List<ProxyConnectorRuleConfiguration> proxyConnectorRuleConfigurations =
                    findProxyConnectorRules( connector.getSourceRepository().getId(),
                                             connector.getTargetRepository().getId(),
                                             allProxyConnectorRuleConfigurations );

                if ( !proxyConnectorRuleConfigurations.isEmpty() )
                {
                    for ( ProxyConnectorRuleConfiguration proxyConnectorRuleConfiguration : proxyConnectorRuleConfigurations )
                    {
                        if ( StringUtils.equals( proxyConnectorRuleConfiguration.getRuleType(),
                                                 ProxyConnectorRuleType.BLACK_LIST.getRuleType() ) )
                        {
                            connector.getBlacklist().add( proxyConnectorRuleConfiguration.getPattern() );
                        }

                        if ( StringUtils.equals( proxyConnectorRuleConfiguration.getRuleType(),
                                                 ProxyConnectorRuleType.WHITE_LIST.getRuleType() ) )
                        {
                            connector.getWhitelist().add( proxyConnectorRuleConfiguration.getPattern() );
                        }
                    }
                }

                // Get other connectors
                List<ProxyConnector> connectors = this.proxyConnectorMap.get( key );
                if ( connectors == null )
                {
                    // Create if we are the first.
                    connectors = new ArrayList<>( 1 );
                }

                // Add the connector.
                connectors.add( connector );

                // Ensure the list is sorted.
                Collections.sort( connectors, proxyOrderSorter );

                // Set the key to the list of connectors.
                this.proxyConnectorMap.put( key, connectors );
            }
            catch ( RepositoryNotFoundException e )
            {
                log.warn( "Unable to use proxy connector: {}", e.getMessage(), e );
            }
            catch ( RepositoryException e )
            {
                log.warn( "Unable to use proxy connector: {}", e.getMessage(), e );
            }


        }

        this.networkProxyMap.clear();

        List<NetworkProxyConfiguration> networkProxies = archivaConfiguration.getConfiguration().getNetworkProxies();
        for ( NetworkProxyConfiguration networkProxyConfig : networkProxies )
        {
            String key = networkProxyConfig.getId();

            ProxyInfo proxy = new ProxyInfo();

            proxy.setType( networkProxyConfig.getProtocol() );
            proxy.setHost( networkProxyConfig.getHost() );
            proxy.setPort( networkProxyConfig.getPort() );
            proxy.setUserName( networkProxyConfig.getUsername() );
            proxy.setPassword( networkProxyConfig.getPassword() );

            this.networkProxyMap.put( key, proxy );
        }

    }

    private List<ProxyConnectorRuleConfiguration> findProxyConnectorRules( String sourceRepository,
                                                                           String targetRepository,
                                                                           List<ProxyConnectorRuleConfiguration> all )
    {
        List<ProxyConnectorRuleConfiguration> proxyConnectorRuleConfigurations = new ArrayList<>();

        for ( ProxyConnectorRuleConfiguration proxyConnectorRuleConfiguration : all )
        {
            for ( ProxyConnectorConfiguration proxyConnector : proxyConnectorRuleConfiguration.getProxyConnectors() )
            {
                if ( StringUtils.equals( sourceRepository, proxyConnector.getSourceRepoId() ) && StringUtils.equals(
                    targetRepository, proxyConnector.getTargetRepoId() ) )
                {
                    proxyConnectorRuleConfigurations.add( proxyConnectorRuleConfiguration );
                }
            }
        }

        return proxyConnectorRuleConfigurations;
    }

    @Override
    public File fetchFromProxies( ManagedRepositoryContent repository, ArtifactReference artifact )
        throws ProxyDownloadException
    {
        File localFile = toLocalFile( repository, artifact );

        Properties requestProperties = new Properties();
        requestProperties.setProperty( "filetype", "artifact" );
        requestProperties.setProperty( "version", artifact.getVersion() );
        requestProperties.setProperty( "managedRepositoryId", repository.getId() );

        List<ProxyConnector> connectors = getProxyConnectors( repository );
        Map<String, Exception> previousExceptions = new LinkedHashMap<>();
        for ( ProxyConnector connector : connectors )
        {
            if ( connector.isDisabled() )
            {
                continue;
            }

            RemoteRepositoryContent targetRepository = connector.getTargetRepository();
            requestProperties.setProperty( "remoteRepositoryId", targetRepository.getId() );

            String targetPath = targetRepository.toPath( artifact );

            if ( SystemUtils.IS_OS_WINDOWS )
            {
                // toPath use system PATH_SEPARATOR so on windows url are \ which doesn't work very well :-)
                targetPath = FilenameUtils.separatorsToUnix( targetPath );
            }

            try
            {
                File downloadedFile =
                    transferFile( connector, targetRepository, targetPath, repository, localFile, requestProperties,
                                  true );

                if ( fileExists( downloadedFile ) )
                {
                    log.debug( "Successfully transferred: {}", downloadedFile.getAbsolutePath() );
                    return downloadedFile;
                }
            }
            catch ( NotFoundException e )
            {
                log.debug( "Artifact {} not found on repository \"{}\".", Keys.toKey( artifact ),
                           targetRepository.getRepository().getId() );
            }
            catch ( NotModifiedException e )
            {
                log.debug( "Artifact {} not updated on repository \"{}\".", Keys.toKey( artifact ),
                           targetRepository.getRepository().getId() );
            }
            catch ( ProxyException | RepositoryAdminException e )
            {
                validatePolicies( this.downloadErrorPolicies, connector.getPolicies(), requestProperties, artifact,
                                  targetRepository, localFile, e, previousExceptions );
            }
        }

        if ( !previousExceptions.isEmpty() )
        {
            throw new ProxyDownloadException( "Failures occurred downloading from some remote repositories",
                                              previousExceptions );
        }

        log.debug( "Exhausted all target repositories, artifact {} not found.", Keys.toKey( artifact ) );

        return null;
    }

    @Override
    public File fetchFromProxies( ManagedRepositoryContent repository, String path )
    {
        File localFile = new File( repository.getRepoRoot(), path );

        // no update policies for these paths
        if ( localFile.exists() )
        {
            return null;
        }

        Properties requestProperties = new Properties();
        requestProperties.setProperty( "filetype", "resource" );
        requestProperties.setProperty( "managedRepositoryId", repository.getId() );

        List<ProxyConnector> connectors = getProxyConnectors( repository );
        for ( ProxyConnector connector : connectors )
        {
            if ( connector.isDisabled() )
            {
                continue;
            }

            RemoteRepositoryContent targetRepository = connector.getTargetRepository();
            requestProperties.setProperty( "remoteRepositoryId", targetRepository.getId() );

            String targetPath = path;

            try
            {
                File downloadedFile =
                    transferFile( connector, targetRepository, targetPath, repository, localFile, requestProperties,
                                  false );

                if ( fileExists( downloadedFile ) )
                {
                    log.debug( "Successfully transferred: {}", downloadedFile.getAbsolutePath() );
                    return downloadedFile;
                }
            }
            catch ( NotFoundException e )
            {
                log.debug( "Resource {} not found on repository \"{}\".", path,
                           targetRepository.getRepository().getId() );
            }
            catch ( NotModifiedException e )
            {
                log.debug( "Resource {} not updated on repository \"{}\".", path,
                           targetRepository.getRepository().getId() );
            }
            catch ( ProxyException e )
            {
                log.warn(
                    "Transfer error from repository {} for resource {}, continuing to next repository. Error message: {}",
                    targetRepository.getRepository().getId(), path, e.getMessage() );
                log.debug( MarkerFactory.getDetachedMarker( "transfer.error" ),
                           "Transfer error from repository \"" + targetRepository.getRepository().getId()
                               + "\" for resource " + path + ", continuing to next repository. Error message: {}",
                           e.getMessage(), e
                );
            }
            catch ( RepositoryAdminException e )
            {
                log.debug( MarkerFactory.getDetachedMarker( "transfer.error" ),
                           "Transfer error from repository {} for resource {}, continuing to next repository. Error message: {}",
                           targetRepository.getRepository().getId(), path, e.getMessage(), e );
                log.debug( MarkerFactory.getDetachedMarker( "transfer.error" ), "Full stack trace", e );
            }
        }

        log.debug( "Exhausted all target repositories, resource {} not found.", path );

        return null;
    }

    @Override
    public ProxyFetchResult fetchMetadataFromProxies( ManagedRepositoryContent repository, String logicalPath )
    {
        File localFile = new File( repository.getRepoRoot(), logicalPath );

        Properties requestProperties = new Properties();
        requestProperties.setProperty( "filetype", "metadata" );
        boolean metadataNeedsUpdating = false;
        long originalTimestamp = getLastModified( localFile );

        List<ProxyConnector> connectors = new ArrayList<>( getProxyConnectors( repository ) );
        for ( ProxyConnector connector : connectors )
        {
            if ( connector.isDisabled() )
            {
                continue;
            }

            RemoteRepositoryContent targetRepository = connector.getTargetRepository();

            File localRepoFile = toLocalRepoFile( repository, targetRepository, logicalPath );
            long originalMetadataTimestamp = getLastModified( localRepoFile );

            try
            {
                transferFile( connector, targetRepository, logicalPath, repository, localRepoFile, requestProperties,
                              true );

                if ( hasBeenUpdated( localRepoFile, originalMetadataTimestamp ) )
                {
                    metadataNeedsUpdating = true;
                }
            }
            catch ( NotFoundException e )
            {

                log.debug( "Metadata {} not found on remote repository '{}'.", logicalPath,
                           targetRepository.getRepository().getId(), e );

            }
            catch ( NotModifiedException e )
            {

                log.debug( "Metadata {} not updated on remote repository '{}'.", logicalPath,
                           targetRepository.getRepository().getId(), e );

            }
            catch ( ProxyException | RepositoryAdminException e )
            {
                log.warn(
                    "Transfer error from repository {} for versioned Metadata {}, continuing to next repository. Error message: {}",
                    targetRepository.getRepository().getId(), logicalPath, e.getMessage() );
                log.debug( "Full stack trace", e );
            }
        }

        if ( hasBeenUpdated( localFile, originalTimestamp ) )
        {
            metadataNeedsUpdating = true;
        }

        if ( metadataNeedsUpdating || !localFile.exists() )
        {
            try
            {
                metadataTools.updateMetadata( repository, logicalPath );
            }
            catch ( RepositoryMetadataException e )
            {
                log.warn( "Unable to update metadata {}:{}", localFile.getAbsolutePath(), e.getMessage(), e );
            }

        }

        if ( fileExists( localFile ) )
        {
            return new ProxyFetchResult( localFile, metadataNeedsUpdating );
        }

        return new ProxyFetchResult( null, false );
    }

    /**
     * @param connector
     * @param remoteRepository
     * @param tmpMd5
     * @param tmpSha1
     * @param tmpResource
     * @param url
     * @param remotePath
     * @param resource
     * @param workingDirectory
     * @param repository
     * @throws ProxyException
     * @throws NotModifiedException
     * @throws org.apache.archiva.admin.model.RepositoryAdminException
     */
    protected void transferResources( ProxyConnector connector, RemoteRepositoryContent remoteRepository, File tmpMd5,
                                      File tmpSha1, File tmpResource, String url, String remotePath, File resource,
                                      File workingDirectory, ManagedRepositoryContent repository )
        throws ProxyException, NotModifiedException, RepositoryAdminException
    {
        Wagon wagon = null;
        try
        {
            RepositoryURL repoUrl = remoteRepository.getURL();
            String protocol = repoUrl.getProtocol();
            NetworkProxy networkProxy = null;
            if ( StringUtils.isNotBlank( connector.getProxyId() ) )
            {
                networkProxy = networkProxyAdmin.getNetworkProxy( connector.getProxyId() );
            }
            WagonFactoryRequest wagonFactoryRequest = new WagonFactoryRequest( "wagon#" + protocol,
                                                                               remoteRepository.getRepository().getExtraHeaders() ).networkProxy(
                networkProxy );
            wagon = wagonFactory.getWagon( wagonFactoryRequest );
            if ( wagon == null )
            {
                throw new ProxyException( "Unsupported target repository protocol: " + protocol );
            }

            if ( wagon == null )
            {
                throw new ProxyException( "Unsupported target repository protocol: " + protocol );
            }

            boolean connected = connectToRepository( connector, wagon, remoteRepository );
            if ( connected )
            {
                transferArtifact( wagon, remoteRepository, remotePath, repository, resource, workingDirectory,
                                  tmpResource );

                // TODO: these should be used to validate the download based on the policies, not always downloaded
                // to
                // save on connections since md5 is rarely used
                transferChecksum( wagon, remoteRepository, remotePath, repository, resource, workingDirectory, ".sha1",
                                  tmpSha1 );
                transferChecksum( wagon, remoteRepository, remotePath, repository, resource, workingDirectory, ".md5",
                                  tmpMd5 );
            }
        }
        catch ( NotFoundException e )
        {
            urlFailureCache.cacheFailure( url );
            throw e;
        }
        catch ( NotModifiedException e )
        {
            // Do not cache url here.
            throw e;
        }
        catch ( ProxyException e )
        {
            urlFailureCache.cacheFailure( url );
            throw e;
        }
        catch ( WagonFactoryException e )
        {
            throw new ProxyException( e.getMessage(), e );
        }
        finally
        {
            if ( wagon != null )
            {
                try
                {
                    wagon.disconnect();
                }
                catch ( ConnectionException e )
                {
                    log.warn( "Unable to disconnect wagon.", e );
                }
            }
        }
    }

    private void transferArtifact( Wagon wagon, RemoteRepositoryContent remoteRepository, String remotePath,
                                   ManagedRepositoryContent repository, File resource, File tmpDirectory,
                                   File destFile )
        throws ProxyException
    {
        transferSimpleFile( wagon, remoteRepository, remotePath, repository, resource, destFile );
    }

    private long getLastModified( File file )
    {
        if ( !file.exists() || !file.isFile() )
        {
            return 0;
        }

        return file.lastModified();
    }

    private boolean hasBeenUpdated( File file, long originalLastModified )
    {
        if ( !file.exists() || !file.isFile() )
        {
            return false;
        }

        long currentLastModified = getLastModified( file );
        return ( currentLastModified > originalLastModified );
    }

    private File toLocalRepoFile( ManagedRepositoryContent repository, RemoteRepositoryContent targetRepository,
                                  String targetPath )
    {
        String repoPath = metadataTools.getRepositorySpecificName( targetRepository, targetPath );
        return new File( repository.getRepoRoot(), repoPath );
    }

    /**
     * Test if the provided ManagedRepositoryContent has any proxies configured for it.
     */
    @Override
    public boolean hasProxies( ManagedRepositoryContent repository )
    {
        synchronized ( this.proxyConnectorMap )
        {
            return this.proxyConnectorMap.containsKey( repository.getId() );
        }
    }

    private File toLocalFile( ManagedRepositoryContent repository, ArtifactReference artifact )
    {
        return repository.toFile( artifact );
    }

    /**
     * Simple method to test if the file exists on the local disk.
     *
     * @param file the file to test. (may be null)
     * @return true if file exists. false if the file param is null, doesn't exist, or is not of type File.
     */
    private boolean fileExists( File file )
    {
        if ( file == null )
        {
            return false;
        }

        if ( !file.exists() )
        {
            return false;
        }

        return file.isFile();
    }

    /**
     * Perform the transfer of the file.
     *
     * @param connector         the connector configuration to use.
     * @param remoteRepository  the remote repository get the resource from.
     * @param remotePath        the path in the remote repository to the resource to get.
     * @param repository        the managed repository that will hold the file
     * @param resource          the local file to place the downloaded resource into
     * @param requestProperties the request properties to utilize for policy handling.
     * @param executeConsumers  whether to execute the consumers after proxying
     * @return the local file that was downloaded, or null if not downloaded.
     * @throws NotFoundException    if the file was not found on the remote repository.
     * @throws NotModifiedException if the localFile was present, and the resource was present on remote repository, but
     *                              the remote resource is not newer than the local File.
     * @throws ProxyException       if transfer was unsuccessful.
     */
    private File transferFile( ProxyConnector connector, RemoteRepositoryContent remoteRepository, String remotePath,
                               ManagedRepositoryContent repository, File resource, Properties requestProperties,
                               boolean executeConsumers )
        throws ProxyException, NotModifiedException, RepositoryAdminException
    {
        String url = remoteRepository.getURL().getUrl();
        if ( !url.endsWith( "/" ) )
        {
            url = url + "/";
        }
        url = url + remotePath;
        requestProperties.setProperty( "url", url );

        // Is a whitelist defined?
        if ( CollectionUtils.isNotEmpty( connector.getWhitelist() ) )
        {
            // Path must belong to whitelist.
            if ( !matchesPattern( remotePath, connector.getWhitelist() ) )
            {
                log.debug( "Path [{}] is not part of defined whitelist (skipping transfer from repository [{}]).",
                           remotePath, remoteRepository.getRepository().getName() );
                return null;
            }
        }

        // Is target path part of blacklist?
        if ( matchesPattern( remotePath, connector.getBlacklist() ) )
        {
            log.debug( "Path [{}] is part of blacklist (skipping transfer from repository [{}]).", remotePath,
                       remoteRepository.getRepository().getName() );
            return null;
        }

        // Handle pre-download policy
        try
        {
            validatePolicies( this.preDownloadPolicies, connector.getPolicies(), requestProperties, resource );
        }
        catch ( PolicyViolationException e )
        {
            String emsg = "Transfer not attempted on " + url + " : " + e.getMessage();
            if ( fileExists( resource ) )
            {
                log.debug( "{} : using already present local file.", emsg );
                return resource;
            }

            log.debug( emsg );
            return null;
        }

        File workingDirectory = createWorkingDirectory( repository );
        File tmpResource = new File( workingDirectory, resource.getName() );
        File tmpMd5 = new File( workingDirectory, resource.getName() + ".md5" );
        File tmpSha1 = new File( workingDirectory, resource.getName() + ".sha1" );

        try
        {

            transferResources( connector, remoteRepository, tmpMd5, tmpSha1, tmpResource, url, remotePath, resource,
                               workingDirectory, repository );

            // Handle post-download policies.
            try
            {
                validatePolicies( this.postDownloadPolicies, connector.getPolicies(), requestProperties, tmpResource );
            }
            catch ( PolicyViolationException e )
            {
                log.warn( "Transfer invalidated from {} : {}", url, e.getMessage() );
                executeConsumers = false;
                if ( !fileExists( tmpResource ) )
                {
                    resource = null;
                }
            }

            if ( resource != null )
            {
                synchronized ( resource.getAbsolutePath().intern() )
                {
                    File directory = resource.getParentFile();
                    moveFileIfExists( tmpMd5, directory );
                    moveFileIfExists( tmpSha1, directory );
                    moveFileIfExists( tmpResource, directory );
                }
            }
        }
        finally
        {
            FileUtils.deleteQuietly( workingDirectory );
        }

        if ( executeConsumers )
        {
            // Just-in-time update of the index and database by executing the consumers for this artifact
            //consumers.executeConsumers( connector.getSourceRepository().getRepository(), resource );
            queueRepositoryTask( connector.getSourceRepository().getRepository().getId(), resource );
        }

        return resource;
    }

    private void queueRepositoryTask( String repositoryId, File localFile )
    {
        RepositoryTask task = new RepositoryTask();
        task.setRepositoryId( repositoryId );
        task.setResourceFile( localFile );
        task.setUpdateRelatedArtifacts( true );
        task.setScanAll( true );

        try
        {
            scheduler.queueTask( task );
        }
        catch ( TaskQueueException e )
        {
            log.error( "Unable to queue repository task to execute consumers on resource file ['" + localFile.getName()
                           + "']." );
        }
    }

    /**
     * Moves the file into repository location if it exists
     *
     * @param fileToMove this could be either the main artifact, sha1 or md5 checksum file.
     * @param directory  directory to write files to
     */
    private void moveFileIfExists( File fileToMove, File directory )
        throws ProxyException
    {
        if ( fileToMove != null && fileToMove.exists() )
        {
            File newLocation = new File( directory, fileToMove.getName() );
            moveTempToTarget( fileToMove, newLocation );
        }
    }

    /**
     * <p>
     * Quietly transfer the checksum file from the remote repository to the local file.
     * </p>
     *
     * @param wagon            the wagon instance (should already be connected) to use.
     * @param remoteRepository the remote repository to transfer from.
     * @param remotePath       the remote path to the resource to get.
     * @param repository       the managed repository that will hold the file
     * @param resource         the local file that should contain the downloaded contents
     * @param tmpDirectory     the temporary directory to download to
     * @param ext              the type of checksum to transfer (example: ".md5" or ".sha1")
     * @throws ProxyException if copying the downloaded file into place did not succeed.
     */
    private void transferChecksum( Wagon wagon, RemoteRepositoryContent remoteRepository, String remotePath,
                                   ManagedRepositoryContent repository, File resource, File tmpDirectory, String ext,
                                   File destFile )
        throws ProxyException
    {
        String url = remoteRepository.getURL().getUrl() + remotePath + ext;

        // Transfer checksum does not use the policy.
        if ( urlFailureCache.hasFailedBefore( url ) )
        {
            return;
        }

        try
        {
            transferSimpleFile( wagon, remoteRepository, remotePath + ext, repository, resource, destFile );
            log.debug( "Checksum {} Downloaded: {} to move to {}", url, destFile, resource );
        }
        catch ( NotFoundException e )
        {
            urlFailureCache.cacheFailure( url );
            log.debug( "Transfer failed, checksum not found: {}", url );
            // Consume it, do not pass this on.
        }
        catch ( NotModifiedException e )
        {
            log.debug( "Transfer skipped, checksum not modified: {}", url );
            // Consume it, do not pass this on.
        }
        catch ( ProxyException e )
        {
            urlFailureCache.cacheFailure( url );
            log.warn( "Transfer failed on checksum: {} : {}", url, e.getMessage(), e );
            // Critical issue, pass it on.
            throw e;
        }
    }

    /**
     * Perform the transfer of the remote file to the local file specified.
     *
     * @param wagon            the wagon instance to use.
     * @param remoteRepository the remote repository to use
     * @param remotePath       the remote path to attempt to get
     * @param repository       the managed repository that will hold the file
     * @param origFile         the local file to save to
     * @throws ProxyException if there was a problem moving the downloaded file into place.
     */
    private void transferSimpleFile( Wagon wagon, RemoteRepositoryContent remoteRepository, String remotePath,
                                     ManagedRepositoryContent repository, File origFile, File destFile )
        throws ProxyException
    {
        assert ( remotePath != null );

        // Transfer the file.
        try
        {
            boolean success = false;

            if ( !origFile.exists() )
            {
                log.debug( "Retrieving {} from {}", remotePath, remoteRepository.getRepository().getName() );
                wagon.get( addParameters( remotePath, remoteRepository.getRepository() ), destFile );
                success = true;

                // You wouldn't get here on failure, a WagonException would have been thrown.
                log.debug( "Downloaded successfully." );
            }
            else
            {
                log.debug( "Retrieving {} from {} if updated", remotePath, remoteRepository.getRepository().getName() );
                success = wagon.getIfNewer( addParameters( remotePath, remoteRepository.getRepository() ), destFile,
                                            origFile.lastModified() );
                if ( !success )
                {
                    throw new NotModifiedException(
                        "Not downloaded, as local file is newer than remote side: " + origFile.getAbsolutePath() );
                }

                if ( destFile.exists() )
                {
                    log.debug( "Downloaded successfully." );
                }
            }
        }
        catch ( ResourceDoesNotExistException e )
        {
            throw new NotFoundException(
                "Resource [" + remoteRepository.getURL() + "/" + remotePath + "] does not exist: " + e.getMessage(),
                e );
        }
        catch ( WagonException e )
        {
            // TODO: shouldn't have to drill into the cause, but TransferFailedException is often not descriptive enough

            String msg =
                "Download failure on resource [" + remoteRepository.getURL() + "/" + remotePath + "]:" + e.getMessage();
            if ( e.getCause() != null )
            {
                msg += " (cause: " + e.getCause() + ")";
            }
            throw new ProxyException( msg, e );
        }
    }

    /**
     * Apply the policies.
     *
     * @param policies  the map of policies to execute. (Map of String policy keys, to {@link DownloadPolicy} objects)
     * @param settings  the map of settings for the policies to execute. (Map of String policy keys, to String policy
     *                  setting)
     * @param request   the request properties (utilized by the {@link DownloadPolicy#applyPolicy(String, Properties, File)}
     *                  )
     * @param localFile the local file (utilized by the {@link DownloadPolicy#applyPolicy(String, Properties, File)})
     * @throws PolicyViolationException
     */
    private void validatePolicies( Map<String, ? extends DownloadPolicy> policies, Map<String, String> settings,
                                   Properties request, File localFile )
        throws PolicyViolationException
    {
        for ( Entry<String, ? extends DownloadPolicy> entry : policies.entrySet() )
        {
            // olamy with spring rolehint is now downloadPolicy#hint
            // so substring after last # to get the hint as with plexus
            String key = StringUtils.substringAfterLast( entry.getKey(), "#" );
            DownloadPolicy policy = entry.getValue();
            String defaultSetting = policy.getDefaultOption();

            String setting = StringUtils.defaultString( settings.get( key ), defaultSetting );

            log.debug( "Applying [{}] policy with [{}]", key, setting );
            try
            {
                policy.applyPolicy( setting, request, localFile );
            }
            catch ( PolicyConfigurationException e )
            {
                log.error( e.getMessage(), e );
            }
        }
    }

    private void validatePolicies( Map<String, DownloadErrorPolicy> policies, Map<String, String> settings,
                                   Properties request, ArtifactReference artifact, RemoteRepositoryContent content,
                                   File localFile, Exception exception, Map<String, Exception> previousExceptions )
        throws ProxyDownloadException
    {
        boolean process = true;
        for ( Entry<String, ? extends DownloadErrorPolicy> entry : policies.entrySet() )
        {

            // olamy with spring rolehint is now downloadPolicy#hint
            // so substring after last # to get the hint as with plexus
            String key = StringUtils.substringAfterLast( entry.getKey(), "#" );
            DownloadErrorPolicy policy = entry.getValue();
            String defaultSetting = policy.getDefaultOption();
            String setting = StringUtils.defaultString( settings.get( key ), defaultSetting );

            log.debug( "Applying [{}] policy with [{}]", key, setting );
            try
            {
                // all policies must approve the exception, any can cancel
                process = policy.applyPolicy( setting, request, localFile, exception, previousExceptions );
                if ( !process )
                {
                    break;
                }
            }
            catch ( PolicyConfigurationException e )
            {
                log.error( e.getMessage(), e );
            }
        }

        if ( process )
        {
            // if the exception was queued, don't throw it
            if ( !previousExceptions.containsKey( content.getId() ) )
            {
                throw new ProxyDownloadException(
                    "An error occurred in downloading from the remote repository, and the policy is to fail immediately",
                    content.getId(), exception );
            }
        }
        else
        {
            // if the exception was queued, but cancelled, remove it
            previousExceptions.remove( content.getId() );
        }

        log.warn(
            "Transfer error from repository {} for artifact {} , continuing to next repository. Error message: {}",
            content.getRepository().getId(), Keys.toKey( artifact ), exception.getMessage() );
        log.debug( "Full stack trace", exception );
    }

    /**
     * Creates a working directory
     *
     * @param repository
     * @return file location of working directory
     */
    private File createWorkingDirectory( ManagedRepositoryContent repository )
    {
        try
        {
            return Files.createTempDirectory( "temp" ).toFile();
        }
        catch ( IOException e )
        {
            throw new RuntimeException( e.getMessage(), e );
        }

    }

    /**
     * Used to move the temporary file to its real destination. This is patterned from the way WagonManager handles its
     * downloaded files.
     *
     * @param temp   The completed download file
     * @param target The final location of the downloaded file
     * @throws ProxyException when the temp file cannot replace the target file
     */
    private void moveTempToTarget( File temp, File target )
        throws ProxyException
    {

        // TODO file lock library
        Lock lock = null;
        try
        {
            lock = fileLockManager.writeFileLock( target );
            if ( lock.getFile().exists() && !lock.getFile().delete() )
            {
                throw new ProxyException( "Unable to overwrite existing target file: " + target.getAbsolutePath() );
            }

            lock.getFile().getParentFile().mkdirs();

            if ( !temp.renameTo( lock.getFile() ) )
            {
                log.warn( "Unable to rename tmp file to its final name... resorting to copy command." );

                try
                {
                    FileUtils.copyFile( temp, lock.getFile() );
                }
                catch ( IOException e )
                {
                    if ( lock.getFile().exists() )
                    {
                        log.debug( "Tried to copy file {} to {} but file with this name already exists.",
                                   temp.getName(), lock.getFile().getAbsolutePath() );
                    }
                    else
                    {
                        throw new ProxyException(
                            "Cannot copy tmp file " + temp.getAbsolutePath() + " to its final location", e );
                    }
                }
                finally
                {
                    FileUtils.deleteQuietly( temp );
                }
            }
        }
        catch ( FileLockException e )
        {
            throw new ProxyException( e.getMessage(), e );
        }
        catch ( FileLockTimeoutException e )
        {
            throw new ProxyException( e.getMessage(), e );
        }
    }

    /**
     * Using wagon, connect to the remote repository.
     *
     * @param connector        the connector configuration to utilize (for obtaining network proxy configuration from)
     * @param wagon            the wagon instance to establish the connection on.
     * @param remoteRepository the remote repository to connect to.
     * @return true if the connection was successful. false if not connected.
     */
    private boolean connectToRepository( ProxyConnector connector, Wagon wagon,
                                         RemoteRepositoryContent remoteRepository )
    {
        boolean connected = false;

        final ProxyInfo networkProxy =
            connector.getProxyId() == null ? null : this.networkProxyMap.get( connector.getProxyId() );

        if ( log.isDebugEnabled() )
        {
            if ( networkProxy != null )
            {
                // TODO: move to proxyInfo.toString()
                String msg = "Using network proxy " + networkProxy.getHost() + ":" + networkProxy.getPort()
                    + " to connect to remote repository " + remoteRepository.getURL();
                if ( networkProxy.getNonProxyHosts() != null )
                {
                    msg += "; excluding hosts: " + networkProxy.getNonProxyHosts();
                }
                if ( StringUtils.isNotBlank( networkProxy.getUserName() ) )
                {
                    msg += "; as user: " + networkProxy.getUserName();
                }
                log.debug( msg );
            }
        }

        AuthenticationInfo authInfo = null;
        String username = remoteRepository.getRepository().getUserName();
        String password = remoteRepository.getRepository().getPassword();

        if ( StringUtils.isNotBlank( username ) && StringUtils.isNotBlank( password ) )
        {
            log.debug( "Using username {} to connect to remote repository {}", username, remoteRepository.getURL() );
            authInfo = new AuthenticationInfo();
            authInfo.setUserName( username );
            authInfo.setPassword( password );
        }

        // Convert seconds to milliseconds
        int timeoutInMilliseconds = remoteRepository.getRepository().getTimeout() * 1000;

        // Set timeout  read and connect
        // FIXME olamy having 2 config values
        wagon.setReadTimeout( timeoutInMilliseconds );
        wagon.setTimeout( timeoutInMilliseconds );

        try
        {
            Repository wagonRepository =
                new Repository( remoteRepository.getId(), remoteRepository.getURL().toString() );
            wagon.connect( wagonRepository, authInfo, networkProxy );
            connected = true;
        }
        catch ( ConnectionException | AuthenticationException e )
        {
            log.warn( "Could not connect to {}: {}", remoteRepository.getRepository().getName(), e.getMessage() );
            connected = false;
        }

        return connected;
    }

    /**
     * Tests whitelist and blacklist patterns against path.
     *
     * @param path     the path to test.
     * @param patterns the list of patterns to check.
     * @return true if the path matches at least 1 pattern in the provided patterns list.
     */
    private boolean matchesPattern( String path, List<String> patterns )
    {
        if ( CollectionUtils.isEmpty( patterns ) )
        {
            return false;
        }

        if ( !path.startsWith( "/" ) )
        {
            path = "/" + path;
        }

        for ( String pattern : patterns )
        {
            if ( !pattern.startsWith( "/" ) )
            {
                pattern = "/" + pattern;
            }

            if ( SelectorUtils.matchPath( pattern, path, false ) )
            {
                return true;
            }
        }

        return false;
    }

    /**
     * TODO: Ensure that list is correctly ordered based on configuration. See MRM-477
     */
    @Override
    public List<ProxyConnector> getProxyConnectors( ManagedRepositoryContent repository )
    {

        if ( !this.proxyConnectorMap.containsKey( repository.getId() ) )
        {
            return Collections.emptyList();
        }
        List<ProxyConnector> ret = new ArrayList<>( this.proxyConnectorMap.get( repository.getId() ) );

        Collections.sort( ret, ProxyConnectorOrderComparator.getInstance() );
        return ret;

    }

    @Override
    public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
    {
        if ( ConfigurationNames.isNetworkProxy( propertyName ) || ConfigurationNames.isManagedRepositories(
            propertyName ) || ConfigurationNames.isRemoteRepositories( propertyName )
            || ConfigurationNames.isProxyConnector( propertyName ) )
        {
            initConnectorsAndNetworkProxies();
        }
    }

    protected String addParameters( String path, RemoteRepository remoteRepository )
    {
        if ( remoteRepository.getExtraParameters().isEmpty() )
        {
            return path;
        }

        boolean question = false;

        StringBuilder res = new StringBuilder( path == null ? "" : path );

        for ( Entry<String, String> entry : remoteRepository.getExtraParameters().entrySet() )
        {
            if ( !question )
            {
                res.append( '?' ).append( entry.getKey() ).append( '=' ).append( entry.getValue() );
            }
        }

        return res.toString();
    }


    @Override
    public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
    {
        /* do nothing */
    }

    public ArchivaConfiguration getArchivaConfiguration()
    {
        return archivaConfiguration;
    }

    public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration )
    {
        this.archivaConfiguration = archivaConfiguration;
    }

    public RepositoryContentFactory getRepositoryFactory()
    {
        return repositoryFactory;
    }

    public void setRepositoryFactory( RepositoryContentFactory repositoryFactory )
    {
        this.repositoryFactory = repositoryFactory;
    }

    public MetadataTools getMetadataTools()
    {
        return metadataTools;
    }

    public void setMetadataTools( MetadataTools metadataTools )
    {
        this.metadataTools = metadataTools;
    }

    public UrlFailureCache getUrlFailureCache()
    {
        return urlFailureCache;
    }

    public void setUrlFailureCache( UrlFailureCache urlFailureCache )
    {
        this.urlFailureCache = urlFailureCache;
    }

    public WagonFactory getWagonFactory()
    {
        return wagonFactory;
    }

    public void setWagonFactory( WagonFactory wagonFactory )
    {
        this.wagonFactory = wagonFactory;
    }

    public Map<String, PreDownloadPolicy> getPreDownloadPolicies()
    {
        return preDownloadPolicies;
    }

    public void setPreDownloadPolicies( Map<String, PreDownloadPolicy> preDownloadPolicies )
    {
        this.preDownloadPolicies = preDownloadPolicies;
    }

    public Map<String, PostDownloadPolicy> getPostDownloadPolicies()
    {
        return postDownloadPolicies;
    }

    public void setPostDownloadPolicies( Map<String, PostDownloadPolicy> postDownloadPolicies )
    {
        this.postDownloadPolicies = postDownloadPolicies;
    }

    public Map<String, DownloadErrorPolicy> getDownloadErrorPolicies()
    {
        return downloadErrorPolicies;
    }

    public void setDownloadErrorPolicies( Map<String, DownloadErrorPolicy> downloadErrorPolicies )
    {
        this.downloadErrorPolicies = downloadErrorPolicies;
    }
}
