package org.apache.maven.wagon;

/*
 * 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.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authentication.AuthenticationInfo;
import org.apache.maven.wagon.authorization.AuthorizationException;
import org.apache.maven.wagon.events.SessionEvent;
import org.apache.maven.wagon.events.SessionEventSupport;
import org.apache.maven.wagon.events.SessionListener;
import org.apache.maven.wagon.events.TransferEvent;
import org.apache.maven.wagon.events.TransferEventSupport;
import org.apache.maven.wagon.events.TransferListener;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.apache.maven.wagon.proxy.ProxyInfoProvider;
import org.apache.maven.wagon.proxy.ProxyUtils;
import org.apache.maven.wagon.repository.Repository;
import org.apache.maven.wagon.repository.RepositoryPermissions;
import org.apache.maven.wagon.resource.Resource;
import org.codehaus.plexus.util.IOUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.List;

import static java.lang.Math.max;
import static java.lang.Math.min;

/**
 * Implementation of common facilities for Wagon providers.
 *
 * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
 */
public abstract class AbstractWagon
    implements Wagon
{
    protected static final int DEFAULT_BUFFER_SIZE = 4 * 1024;
    protected static final int MAXIMUM_BUFFER_SIZE = 512 * 1024;

    /**
     * To efficiently buffer data, use a multiple of 4 KiB as this is likely to match the hardware
     * buffer size of certain storage devices.
     */
    protected static final int BUFFER_SEGMENT_SIZE = 4 * 1024;

    /**
     * The desired minimum amount of chunks in which a {@link Resource} shall be
     * {@link #transfer(Resource, InputStream, OutputStream, int, long) transferred}.
     * This corresponds to the minimum times {@link #fireTransferProgress(TransferEvent, byte[], int)}
     * is executed. 100 notifications is a conservative value that will lead to small chunks for
     * any artifact less that {@link #BUFFER_SEGMENT_SIZE} * {@link #MINIMUM_AMOUNT_OF_TRANSFER_CHUNKS}
     * in size.
     */
    protected static final int MINIMUM_AMOUNT_OF_TRANSFER_CHUNKS = 100;

    protected Repository repository;

    protected SessionEventSupport sessionEventSupport = new SessionEventSupport();

    protected TransferEventSupport transferEventSupport = new TransferEventSupport();

    protected AuthenticationInfo authenticationInfo;

    protected boolean interactive = true;


    private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;

    /**
     * read timeout value
     *
     * @since 2.2
     */
    private int readTimeout =
        Integer.parseInt( System.getProperty( "maven.wagon.rto", Integer.toString( Wagon.DEFAULT_READ_TIMEOUT ) ) );

    private ProxyInfoProvider proxyInfoProvider;

    /**
     * @deprecated
     */
    protected ProxyInfo proxyInfo;

    private RepositoryPermissions permissionsOverride;

    // ----------------------------------------------------------------------
    // Accessors
    // ----------------------------------------------------------------------

    public Repository getRepository()
    {
        return repository;
    }

    public ProxyInfo getProxyInfo()
    {
        return proxyInfoProvider != null ? proxyInfoProvider.getProxyInfo( null ) : null;
    }

    public AuthenticationInfo getAuthenticationInfo()
    {
        return authenticationInfo;
    }

    // ----------------------------------------------------------------------
    // Connection
    // ----------------------------------------------------------------------

    public void openConnection()
        throws ConnectionException, AuthenticationException
    {
        try
        {
            openConnectionInternal();
        }
        catch ( ConnectionException e )
        {
            fireSessionConnectionRefused();

            throw e;
        }
        catch ( AuthenticationException e )
        {
            fireSessionConnectionRefused();

            throw e;
        }
    }

    public void connect( Repository repository )
        throws ConnectionException, AuthenticationException
    {
        connect( repository, null, (ProxyInfoProvider) null );
    }

    public void connect( Repository repository, ProxyInfo proxyInfo )
        throws ConnectionException, AuthenticationException
    {
        connect( repository, null, proxyInfo );
    }

    public void connect( Repository repository, ProxyInfoProvider proxyInfoProvider )
        throws ConnectionException, AuthenticationException
    {
        connect( repository, null, proxyInfoProvider );
    }

    public void connect( Repository repository, AuthenticationInfo authenticationInfo )
        throws ConnectionException, AuthenticationException
    {
        connect( repository, authenticationInfo, (ProxyInfoProvider) null );
    }

    public void connect( Repository repository, AuthenticationInfo authenticationInfo, ProxyInfo proxyInfo )
        throws ConnectionException, AuthenticationException
    {
        final ProxyInfo proxy = proxyInfo;
        connect( repository, authenticationInfo, new ProxyInfoProvider()
        {
            public ProxyInfo getProxyInfo( String protocol )
            {
                if ( protocol == null || proxy == null || protocol.equalsIgnoreCase( proxy.getType() ) )
                {
                    return proxy;
                }
                else
                {
                    return null;
                }
            }
        } );
    }

    public void connect( Repository repository, AuthenticationInfo authenticationInfo,
                         ProxyInfoProvider proxyInfoProvider )
        throws ConnectionException, AuthenticationException
    {
        if ( repository == null )
        {
            throw new NullPointerException( "repository cannot be null" );
        }

        if ( permissionsOverride != null )
        {
            repository.setPermissions( permissionsOverride );
        }

        this.repository = repository;

        if ( authenticationInfo == null )
        {
            authenticationInfo = new AuthenticationInfo();
        }

        if ( authenticationInfo.getUserName() == null )
        {
            // Get user/pass that were encoded in the URL.
            if ( repository.getUsername() != null )
            {
                authenticationInfo.setUserName( repository.getUsername() );
                if ( repository.getPassword() != null && authenticationInfo.getPassword() == null )
                {
                    authenticationInfo.setPassword( repository.getPassword() );
                }
            }
        }

        this.authenticationInfo = authenticationInfo;

        this.proxyInfoProvider = proxyInfoProvider;

        fireSessionOpening();

        openConnection();

        fireSessionOpened();
    }

    protected abstract void openConnectionInternal()
        throws ConnectionException, AuthenticationException;

    public void disconnect()
        throws ConnectionException
    {
        fireSessionDisconnecting();

        try
        {
            closeConnection();
        }
        catch ( ConnectionException e )
        {
            fireSessionError( e );
            throw e;
        }

        fireSessionDisconnected();
    }

    protected abstract void closeConnection()
        throws ConnectionException;

    protected void createParentDirectories( File destination )
        throws TransferFailedException
    {
        File destinationDirectory = destination.getParentFile();
        try
        {
            destinationDirectory = destinationDirectory.getCanonicalFile();
        }
        catch ( IOException e )
        {
            // not essential to have a canonical file
        }
        if ( destinationDirectory != null && !destinationDirectory.exists() )
        {
            destinationDirectory.mkdirs();
            if ( !destinationDirectory.exists() )
            {
                throw new TransferFailedException(
                    "Specified destination directory cannot be created: " + destinationDirectory );
            }
        }
    }

    public void setTimeout( int timeoutValue )
    {
        connectionTimeout = timeoutValue;
    }

    public int getTimeout()
    {
        return connectionTimeout;
    }

    // ----------------------------------------------------------------------
    // Stream i/o
    // ----------------------------------------------------------------------

    protected void getTransfer( Resource resource, File destination, InputStream input )
        throws TransferFailedException
    {
        getTransfer( resource, destination, input, true, Long.MAX_VALUE );
    }

    protected void getTransfer( Resource resource, OutputStream output, InputStream input )
        throws TransferFailedException
    {
        getTransfer( resource, output, input, true, Long.MAX_VALUE );
    }

    @Deprecated
    protected void getTransfer( Resource resource, File destination, InputStream input, boolean closeInput,
                                int maxSize )
        throws TransferFailedException
    {
        getTransfer( resource, destination, input, closeInput, (long) maxSize );
    }

    protected void getTransfer( Resource resource, File destination, InputStream input, boolean closeInput,
                                long maxSize )
        throws TransferFailedException
    {
        // ensure that the destination is created only when we are ready to transfer
        fireTransferDebug( "attempting to create parent directories for destination: " + destination.getName() );
        createParentDirectories( destination );

        fireGetStarted( resource, destination );

        OutputStream output = null;
        try
        {
            output = new LazyFileOutputStream( destination );
            getTransfer( resource, output, input, closeInput, maxSize );
            output.close();
            output = null;
        }
        catch ( final IOException e )
        {
            if ( destination.exists() )
            {
                boolean deleted = destination.delete();

                if ( !deleted )
                {
                    destination.deleteOnExit();
                }
            }

            fireTransferError( resource, e, TransferEvent.REQUEST_GET );

            String msg = "GET request of: " + resource.getName() + " from " + repository.getName() + " failed";

            throw new TransferFailedException( msg, e );
        }
        catch ( TransferFailedException e )
        {
            if ( destination.exists() )
            {
                boolean deleted = destination.delete();

                if ( !deleted )
                {
                    destination.deleteOnExit();
                }
            }
            throw e;
        }
        finally
        {
            IOUtil.close( output );
        }

        fireGetCompleted( resource, destination );
    }

    @Deprecated
    protected void getTransfer( Resource resource, OutputStream output, InputStream input, boolean closeInput,
                                int maxSize )
        throws TransferFailedException
    {
        getTransfer( resource, output, input, closeInput, (long) maxSize );
    }

    protected void getTransfer( Resource resource, OutputStream output, InputStream input, boolean closeInput,
                                long maxSize )
        throws TransferFailedException
    {
        try
        {
            transfer( resource, input, output, TransferEvent.REQUEST_GET, maxSize );

            finishGetTransfer( resource, input, output );

            if ( closeInput )
            {
                input.close();
                input = null;
            }

        }
        catch ( IOException e )
        {
            fireTransferError( resource, e, TransferEvent.REQUEST_GET );

            String msg = "GET request of: " + resource.getName() + " from " + repository.getName() + " failed";

            throw new TransferFailedException( msg, e );
        }
        finally
        {
            if ( closeInput )
            {
                IOUtil.close( input );
            }

            cleanupGetTransfer( resource );
        }
    }

    protected void finishGetTransfer( Resource resource, InputStream input, OutputStream output )
        throws TransferFailedException
    {
    }

    protected void cleanupGetTransfer( Resource resource )
    {
    }

    protected void putTransfer( Resource resource, File source, OutputStream output, boolean closeOutput )
        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
    {
        firePutStarted( resource, source );

        transfer( resource, source, output, closeOutput );

        firePutCompleted( resource, source );
    }

    /**
     * Write from {@link File} to {@link OutputStream}
     *
     * @param resource    resource to transfer
     * @param source      file to read from
     * @param output      output stream
     * @param closeOutput whether the output stream should be closed or not
     * @throws TransferFailedException
     * @throws ResourceDoesNotExistException
     * @throws AuthorizationException
     * @since 1.0-beta-1
     */
    protected void transfer( Resource resource, File source, OutputStream output, boolean closeOutput )
        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
    {
        InputStream input = null;

        try
        {
            input = new FileInputStream( source );

            putTransfer( resource, input, output, closeOutput );

            input.close();
            input = null;
        }
        catch ( FileNotFoundException e )
        {
            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );

            throw new TransferFailedException( "Specified source file does not exist: " + source, e );
        }
        catch ( final IOException e )
        {
            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );

            throw new TransferFailedException( "Failure transferring " + source, e );
        }
        finally
        {
            IOUtil.close( input );
        }
    }

    protected void putTransfer( Resource resource, InputStream input, OutputStream output, boolean closeOutput )
        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
    {
        try
        {
            transfer( resource, input, output, TransferEvent.REQUEST_PUT,
                      resource.getContentLength() == WagonConstants.UNKNOWN_LENGTH
                          ? Long.MAX_VALUE
                          : resource.getContentLength() );

            finishPutTransfer( resource, input, output );

            if ( closeOutput )
            {
                output.close();
                output = null;
            }
        }
        catch ( IOException e )
        {
            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );

            String msg = "PUT request to: " + resource.getName() + " in " + repository.getName() + " failed";

            throw new TransferFailedException( msg, e );
        }
        finally
        {
            if ( closeOutput )
            {
                IOUtil.close( output );
            }

            cleanupPutTransfer( resource );
        }
    }

    protected void cleanupPutTransfer( Resource resource )
    {
    }

    protected void finishPutTransfer( Resource resource, InputStream input, OutputStream output )
        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
    {
    }

    /**
     * Write from {@link InputStream} to {@link OutputStream}.
     * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, int)} with a maxSize equals to
     * {@link Integer#MAX_VALUE}
     *
     * @param resource    resource to transfer
     * @param input       input stream
     * @param output      output stream
     * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
     * @throws IOException
     */
    protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType )
        throws IOException
    {
        transfer( resource, input, output, requestType, Long.MAX_VALUE );
    }

    /**
     * Write from {@link InputStream} to {@link OutputStream}.
     * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, int)} with a maxSize equals to
     * {@link Integer#MAX_VALUE}
     *
     * @param resource    resource to transfer
     * @param input       input stream
     * @param output      output stream
     * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
     * @param maxSize     size of the buffer
     * @throws IOException
     * @deprecated Please use the transfer using long as type of maxSize
     */
    @Deprecated
    protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType, int maxSize )
        throws IOException
    {
        transfer( resource, input, output, requestType, (long) maxSize );
    }

    /**
     * Write from {@link InputStream} to {@link OutputStream}.
     * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, long)} with a maxSize equals to
     * {@link Integer#MAX_VALUE}
     *
     * @param resource    resource to transfer
     * @param input       input stream
     * @param output      output stream
     * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
     * @param maxSize     size of the buffer
     * @throws IOException
     */
    protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType, long maxSize )
        throws IOException
    {
        ByteBuffer buffer = ByteBuffer.allocate( getBufferCapacityForTransfer( resource.getContentLength() ) );
        int halfBufferCapacity = buffer.capacity() / 2;

        TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_PROGRESS, requestType );
        transferEvent.setTimestamp( System.currentTimeMillis() );

        ReadableByteChannel in = Channels.newChannel( input );

        long remaining = maxSize;
        while ( remaining > 0L )
        {
            int read = in.read( buffer );

            if ( read == -1 )
            {
                // EOF, but some data has not been written yet.
                if ( buffer.position() != 0 )
                {
                    buffer.flip();
                    fireTransferProgress( transferEvent, buffer.array(), buffer.limit() );
                    output.write( buffer.array(), 0, buffer.limit() );
                }

                break;
            }

            // Prevent minichunking / fragmentation: when less than half the buffer is utilized,
            // read some more bytes before writing and firing progress.
            if ( buffer.position() < halfBufferCapacity )
            {
                continue;
            }

            buffer.flip();
            fireTransferProgress( transferEvent, buffer.array(), buffer.limit() );
            output.write( buffer.array(), 0, buffer.limit() );
            remaining -= buffer.limit();
            buffer.clear();
        }
        output.flush();
    }

    /**
     * Provides a buffer size for efficiently transferring the given amount of bytes such that
     * it is not fragmented into too many chunks. For larger files larger buffers are provided such that downstream
     * {@link #fireTransferProgress(TransferEvent, byte[], int) listeners} are not notified too frequently.
     * For instance, transferring gigabyte-sized resources would result in millions of notifications when using
     * only a few kibibytes of buffer, drastically slowing down transfer since transfer progress listeners and
     * notifications are synchronous and may block, e.g., when writing download progress status to console.
     *
     * @param numberOfBytes can be 0 or less, in which case a default buffer size is used.
     * @return a byte buffer suitable for transferring the given amount of bytes without too many chunks.
     */
    protected int getBufferCapacityForTransfer( long numberOfBytes )
    {
        if ( numberOfBytes <= 0L )
        {
            return DEFAULT_BUFFER_SIZE;
        }

        final int numberOfBufferSegments = (int)
            numberOfBytes / ( BUFFER_SEGMENT_SIZE * MINIMUM_AMOUNT_OF_TRANSFER_CHUNKS );
        final int potentialBufferSize = numberOfBufferSegments * BUFFER_SEGMENT_SIZE;
        return min( MAXIMUM_BUFFER_SIZE, max( DEFAULT_BUFFER_SIZE, potentialBufferSize ) );
    }

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    protected void fireTransferProgress( TransferEvent transferEvent, byte[] buffer, int n )
    {
        transferEventSupport.fireTransferProgress( transferEvent, buffer, n );
    }

    protected void fireGetCompleted( Resource resource, File localFile )
    {
        long timestamp = System.currentTimeMillis();

        TransferEvent transferEvent =
            new TransferEvent( this, resource, TransferEvent.TRANSFER_COMPLETED, TransferEvent.REQUEST_GET );

        transferEvent.setTimestamp( timestamp );

        transferEvent.setLocalFile( localFile );

        transferEventSupport.fireTransferCompleted( transferEvent );
    }

    protected void fireGetStarted( Resource resource, File localFile )
    {
        long timestamp = System.currentTimeMillis();

        TransferEvent transferEvent =
            new TransferEvent( this, resource, TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_GET );

        transferEvent.setTimestamp( timestamp );

        transferEvent.setLocalFile( localFile );

        transferEventSupport.fireTransferStarted( transferEvent );
    }

    protected void fireGetInitiated( Resource resource, File localFile )
    {
        long timestamp = System.currentTimeMillis();

        TransferEvent transferEvent =
            new TransferEvent( this, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_GET );

        transferEvent.setTimestamp( timestamp );

        transferEvent.setLocalFile( localFile );

        transferEventSupport.fireTransferInitiated( transferEvent );
    }

    protected void firePutInitiated( Resource resource, File localFile )
    {
        long timestamp = System.currentTimeMillis();

        TransferEvent transferEvent =
            new TransferEvent( this, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_PUT );

        transferEvent.setTimestamp( timestamp );

        transferEvent.setLocalFile( localFile );

        transferEventSupport.fireTransferInitiated( transferEvent );
    }

    protected void firePutCompleted( Resource resource, File localFile )
    {
        long timestamp = System.currentTimeMillis();

        TransferEvent transferEvent =
            new TransferEvent( this, resource, TransferEvent.TRANSFER_COMPLETED, TransferEvent.REQUEST_PUT );

        transferEvent.setTimestamp( timestamp );

        transferEvent.setLocalFile( localFile );

        transferEventSupport.fireTransferCompleted( transferEvent );
    }

    protected void firePutStarted( Resource resource, File localFile )
    {
        long timestamp = System.currentTimeMillis();

        TransferEvent transferEvent =
            new TransferEvent( this, resource, TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_PUT );

        transferEvent.setTimestamp( timestamp );

        transferEvent.setLocalFile( localFile );

        transferEventSupport.fireTransferStarted( transferEvent );
    }

    protected void fireSessionDisconnected()
    {
        long timestamp = System.currentTimeMillis();

        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_DISCONNECTED );

        sessionEvent.setTimestamp( timestamp );

        sessionEventSupport.fireSessionDisconnected( sessionEvent );
    }

    protected void fireSessionDisconnecting()
    {
        long timestamp = System.currentTimeMillis();

        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_DISCONNECTING );

        sessionEvent.setTimestamp( timestamp );

        sessionEventSupport.fireSessionDisconnecting( sessionEvent );
    }

    protected void fireSessionLoggedIn()
    {
        long timestamp = System.currentTimeMillis();

        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_LOGGED_IN );

        sessionEvent.setTimestamp( timestamp );

        sessionEventSupport.fireSessionLoggedIn( sessionEvent );
    }

    protected void fireSessionLoggedOff()
    {
        long timestamp = System.currentTimeMillis();

        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_LOGGED_OFF );

        sessionEvent.setTimestamp( timestamp );

        sessionEventSupport.fireSessionLoggedOff( sessionEvent );
    }

    protected void fireSessionOpened()
    {
        long timestamp = System.currentTimeMillis();

        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_OPENED );

        sessionEvent.setTimestamp( timestamp );

        sessionEventSupport.fireSessionOpened( sessionEvent );
    }

    protected void fireSessionOpening()
    {
        long timestamp = System.currentTimeMillis();

        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_OPENING );

        sessionEvent.setTimestamp( timestamp );

        sessionEventSupport.fireSessionOpening( sessionEvent );
    }

    protected void fireSessionConnectionRefused()
    {
        long timestamp = System.currentTimeMillis();

        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_CONNECTION_REFUSED );

        sessionEvent.setTimestamp( timestamp );

        sessionEventSupport.fireSessionConnectionRefused( sessionEvent );
    }

    protected void fireSessionError( Exception exception )
    {
        long timestamp = System.currentTimeMillis();

        SessionEvent sessionEvent = new SessionEvent( this, exception );

        sessionEvent.setTimestamp( timestamp );

        sessionEventSupport.fireSessionError( sessionEvent );

    }

    protected void fireTransferDebug( String message )
    {
        transferEventSupport.fireDebug( message );
    }

    protected void fireSessionDebug( String message )
    {
        sessionEventSupport.fireDebug( message );
    }

    public boolean hasTransferListener( TransferListener listener )
    {
        return transferEventSupport.hasTransferListener( listener );
    }

    public void addTransferListener( TransferListener listener )
    {
        transferEventSupport.addTransferListener( listener );
    }

    public void removeTransferListener( TransferListener listener )
    {
        transferEventSupport.removeTransferListener( listener );
    }

    public void addSessionListener( SessionListener listener )
    {
        sessionEventSupport.addSessionListener( listener );
    }

    public boolean hasSessionListener( SessionListener listener )
    {
        return sessionEventSupport.hasSessionListener( listener );
    }

    public void removeSessionListener( SessionListener listener )
    {
        sessionEventSupport.removeSessionListener( listener );
    }

    protected void fireTransferError( Resource resource, Exception e, int requestType )
    {
        TransferEvent transferEvent = new TransferEvent( this, resource, e, requestType );
        transferEventSupport.fireTransferError( transferEvent );
    }


    public SessionEventSupport getSessionEventSupport()
    {
        return sessionEventSupport;
    }

    public void setSessionEventSupport( SessionEventSupport sessionEventSupport )
    {
        this.sessionEventSupport = sessionEventSupport;
    }

    public TransferEventSupport getTransferEventSupport()
    {
        return transferEventSupport;
    }

    public void setTransferEventSupport( TransferEventSupport transferEventSupport )
    {
        this.transferEventSupport = transferEventSupport;
    }

    /**
     * This method is used if you are not streaming the transfer, to make sure any listeners dependent on state
     * (eg checksum observers) succeed.
     */
    protected void postProcessListeners( Resource resource, File source, int requestType )
        throws TransferFailedException
    {
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];

        TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_PROGRESS, requestType );
        transferEvent.setTimestamp( System.currentTimeMillis() );
        transferEvent.setLocalFile( source );

        InputStream input = null;
        try
        {
            input = new FileInputStream( source );

            while ( true )
            {
                int n = input.read( buffer );

                if ( n == -1 )
                {
                    break;
                }

                fireTransferProgress( transferEvent, buffer, n );
            }

            input.close();
            input = null;
        }
        catch ( IOException e )
        {
            fireTransferError( resource, e, requestType );

            throw new TransferFailedException( "Failed to post-process the source file", e );
        }
        finally
        {
            IOUtil.close( input );
        }
    }

    public void putDirectory( File sourceDirectory, String destinationDirectory )
        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
    {
        throw new UnsupportedOperationException( "The wagon you are using has not implemented putDirectory()" );
    }

    public boolean supportsDirectoryCopy()
    {
        return false;
    }

    protected static String getPath( String basedir, String dir )
    {
        String path;
        path = basedir;
        if ( !basedir.endsWith( "/" ) && !dir.startsWith( "/" ) )
        {
            path += "/";
        }
        path += dir;
        return path;
    }

    public boolean isInteractive()
    {
        return interactive;
    }

    public void setInteractive( boolean interactive )
    {
        this.interactive = interactive;
    }

    public List<String> getFileList( String destinationDirectory )
        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
    {
        throw new UnsupportedOperationException( "The wagon you are using has not implemented getFileList()" );
    }

    public boolean resourceExists( String resourceName )
        throws TransferFailedException, AuthorizationException
    {
        throw new UnsupportedOperationException( "The wagon you are using has not implemented resourceExists()" );
    }

    protected ProxyInfo getProxyInfo( String protocol, String host )
    {
        if ( proxyInfoProvider != null )
        {
            ProxyInfo proxyInfo = proxyInfoProvider.getProxyInfo( protocol );
            if ( !ProxyUtils.validateNonProxyHosts( proxyInfo, host ) )
            {
                return proxyInfo;
            }
        }
        return null;
    }

    public RepositoryPermissions getPermissionsOverride()
    {
        return permissionsOverride;
    }

    public void setPermissionsOverride( RepositoryPermissions permissionsOverride )
    {
        this.permissionsOverride = permissionsOverride;
    }

    public void setReadTimeout( int readTimeout )
    {
        this.readTimeout = readTimeout;
    }

    public int getReadTimeout()
    {
        return this.readTimeout;
    }
}
