001package org.apache.maven.wagon;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.maven.wagon.authentication.AuthenticationException;
023import org.apache.maven.wagon.authentication.AuthenticationInfo;
024import org.apache.maven.wagon.authorization.AuthorizationException;
025import org.apache.maven.wagon.events.SessionEvent;
026import org.apache.maven.wagon.events.SessionEventSupport;
027import org.apache.maven.wagon.events.SessionListener;
028import org.apache.maven.wagon.events.TransferEvent;
029import org.apache.maven.wagon.events.TransferEventSupport;
030import org.apache.maven.wagon.events.TransferListener;
031import org.apache.maven.wagon.proxy.ProxyInfo;
032import org.apache.maven.wagon.proxy.ProxyInfoProvider;
033import org.apache.maven.wagon.proxy.ProxyUtils;
034import org.apache.maven.wagon.repository.Repository;
035import org.apache.maven.wagon.repository.RepositoryPermissions;
036import org.apache.maven.wagon.resource.Resource;
037import org.codehaus.plexus.util.IOUtil;
038
039import java.io.File;
040import java.io.FileInputStream;
041import java.io.FileNotFoundException;
042import java.io.IOException;
043import java.io.InputStream;
044import java.io.OutputStream;
045import java.util.List;
046
047/**
048 * Implementation of common facilities for Wagon providers.
049 *
050 * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
051 */
052public abstract class AbstractWagon
053    implements Wagon
054{
055    protected static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
056
057    protected Repository repository;
058
059    protected SessionEventSupport sessionEventSupport = new SessionEventSupport();
060
061    protected TransferEventSupport transferEventSupport = new TransferEventSupport();
062
063    protected AuthenticationInfo authenticationInfo;
064
065    protected boolean interactive = true;
066
067
068    private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
069
070    /**
071     * read timeout value
072     *
073     * @since 2.2
074     */
075    private int readTimeout =
076        Integer.parseInt( System.getProperty( "maven.wagon.rto", Integer.toString( Wagon.DEFAULT_READ_TIMEOUT ) ) );
077
078    private ProxyInfoProvider proxyInfoProvider;
079
080    /**
081     * @deprecated
082     */
083    protected ProxyInfo proxyInfo;
084
085    private RepositoryPermissions permissionsOverride;
086
087    // ----------------------------------------------------------------------
088    // Accessors
089    // ----------------------------------------------------------------------
090
091    public Repository getRepository()
092    {
093        return repository;
094    }
095
096    public ProxyInfo getProxyInfo()
097    {
098        return proxyInfoProvider != null ? proxyInfoProvider.getProxyInfo( null ) : null;
099    }
100
101    public AuthenticationInfo getAuthenticationInfo()
102    {
103        return authenticationInfo;
104    }
105
106    // ----------------------------------------------------------------------
107    // Connection
108    // ----------------------------------------------------------------------
109
110    public void openConnection()
111        throws ConnectionException, AuthenticationException
112    {
113        try
114        {
115            openConnectionInternal();
116        }
117        catch ( ConnectionException e )
118        {
119            fireSessionConnectionRefused();
120
121            throw e;
122        }
123        catch ( AuthenticationException e )
124        {
125            fireSessionConnectionRefused();
126
127            throw e;
128        }
129    }
130
131    public void connect( Repository repository )
132        throws ConnectionException, AuthenticationException
133    {
134        connect( repository, null, (ProxyInfoProvider) null );
135    }
136
137    public void connect( Repository repository, ProxyInfo proxyInfo )
138        throws ConnectionException, AuthenticationException
139    {
140        connect( repository, null, proxyInfo );
141    }
142
143    public void connect( Repository repository, ProxyInfoProvider proxyInfoProvider )
144        throws ConnectionException, AuthenticationException
145    {
146        connect( repository, null, proxyInfoProvider );
147    }
148
149    public void connect( Repository repository, AuthenticationInfo authenticationInfo )
150        throws ConnectionException, AuthenticationException
151    {
152        connect( repository, authenticationInfo, (ProxyInfoProvider) null );
153    }
154
155    public void connect( Repository repository, AuthenticationInfo authenticationInfo, ProxyInfo proxyInfo )
156        throws ConnectionException, AuthenticationException
157    {
158        final ProxyInfo proxy = proxyInfo;
159        connect( repository, authenticationInfo, new ProxyInfoProvider()
160        {
161            public ProxyInfo getProxyInfo( String protocol )
162            {
163                if ( protocol == null || proxy == null || protocol.equalsIgnoreCase( proxy.getType() ) )
164                {
165                    return proxy;
166                }
167                else
168                {
169                    return null;
170                }
171            }
172        } );
173        this.proxyInfo = proxyInfo;
174    }
175
176    public void connect( Repository repository, AuthenticationInfo authenticationInfo,
177                         ProxyInfoProvider proxyInfoProvider )
178        throws ConnectionException, AuthenticationException
179    {
180        if ( repository == null )
181        {
182            throw new IllegalStateException( "The repository specified cannot be null." );
183        }
184
185        if ( permissionsOverride != null )
186        {
187            repository.setPermissions( permissionsOverride );
188        }
189
190        this.repository = repository;
191
192        if ( authenticationInfo == null )
193        {
194            authenticationInfo = new AuthenticationInfo();
195        }
196
197        if ( authenticationInfo.getUserName() == null )
198        {
199            // Get user/pass that were encoded in the URL.
200            if ( repository.getUsername() != null )
201            {
202                authenticationInfo.setUserName( repository.getUsername() );
203                if ( repository.getPassword() != null && authenticationInfo.getPassword() == null )
204                {
205                    authenticationInfo.setPassword( repository.getPassword() );
206                }
207            }
208        }
209
210        // TODO: Do these needs to be fields, or are they only used in openConnection()?
211        this.authenticationInfo = authenticationInfo;
212
213        this.proxyInfoProvider = proxyInfoProvider;
214
215        fireSessionOpening();
216
217        openConnection();
218
219        fireSessionOpened();
220    }
221
222    protected abstract void openConnectionInternal()
223        throws ConnectionException, AuthenticationException;
224
225    public void disconnect()
226        throws ConnectionException
227    {
228        fireSessionDisconnecting();
229
230        try
231        {
232            closeConnection();
233        }
234        catch ( ConnectionException e )
235        {
236            fireSessionError( e );
237            throw e;
238        }
239
240        fireSessionDisconnected();
241    }
242
243    protected abstract void closeConnection()
244        throws ConnectionException;
245
246    protected void createParentDirectories( File destination )
247        throws TransferFailedException
248    {
249        File destinationDirectory = destination.getParentFile();
250        try
251        {
252            destinationDirectory = destinationDirectory.getCanonicalFile();
253        }
254        catch ( IOException e )
255        {
256            // not essential to have a canonical file
257        }
258        if ( destinationDirectory != null && !destinationDirectory.exists() )
259        {
260            destinationDirectory.mkdirs();
261            if ( !destinationDirectory.exists() )
262            {
263                throw new TransferFailedException(
264                    "Specified destination directory cannot be created: " + destinationDirectory );
265            }
266        }
267    }
268
269    public void setTimeout( int timeoutValue )
270    {
271        connectionTimeout = timeoutValue;
272    }
273
274    public int getTimeout()
275    {
276        return connectionTimeout;
277    }
278
279    // ----------------------------------------------------------------------
280    // Stream i/o
281    // ----------------------------------------------------------------------
282
283    protected void getTransfer( Resource resource, File destination, InputStream input )
284        throws TransferFailedException
285    {
286        getTransfer( resource, destination, input, true, Long.MAX_VALUE );
287    }
288
289    protected void getTransfer( Resource resource, OutputStream output, InputStream input )
290        throws TransferFailedException
291    {
292        getTransfer( resource, output, input, true, Long.MAX_VALUE );
293    }
294
295    @Deprecated
296    protected void getTransfer( Resource resource, File destination, InputStream input, boolean closeInput,
297                                int maxSize )
298        throws TransferFailedException
299    {
300        getTransfer( resource, destination, input, closeInput, (long) maxSize );
301    }
302
303    protected void getTransfer( Resource resource, File destination, InputStream input, boolean closeInput,
304                                long maxSize )
305        throws TransferFailedException
306    {
307        // ensure that the destination is created only when we are ready to transfer
308        fireTransferDebug( "attempting to create parent directories for destination: " + destination.getName() );
309        createParentDirectories( destination );
310
311        OutputStream output = new LazyFileOutputStream( destination );
312
313        fireGetStarted( resource, destination );
314
315        try
316        {
317            getTransfer( resource, output, input, closeInput, maxSize );
318        }
319        catch ( TransferFailedException e )
320        {
321            if ( destination.exists() )
322            {
323                boolean deleted = destination.delete();
324
325                if ( !deleted )
326                {
327                    destination.deleteOnExit();
328                }
329            }
330            throw e;
331        }
332        finally
333        {
334            IOUtil.close( output );
335        }
336
337        fireGetCompleted( resource, destination );
338    }
339
340    @Deprecated
341    protected void getTransfer( Resource resource, OutputStream output, InputStream input, boolean closeInput,
342                                int maxSize )
343        throws TransferFailedException
344    {
345        getTransfer( resource, output, input, closeInput, (long) maxSize );
346    }
347
348    protected void getTransfer( Resource resource, OutputStream output, InputStream input, boolean closeInput,
349                                long maxSize )
350        throws TransferFailedException
351    {
352        try
353        {
354            transfer( resource, input, output, TransferEvent.REQUEST_GET, maxSize );
355
356            finishGetTransfer( resource, input, output );
357        }
358        catch ( IOException e )
359        {
360            fireTransferError( resource, e, TransferEvent.REQUEST_GET );
361
362            String msg = "GET request of: " + resource.getName() + " from " + repository.getName() + " failed";
363
364            throw new TransferFailedException( msg, e );
365        }
366        finally
367        {
368            if ( closeInput )
369            {
370                IOUtil.close( input );
371            }
372
373            cleanupGetTransfer( resource );
374        }
375    }
376
377    protected void finishGetTransfer( Resource resource, InputStream input, OutputStream output )
378        throws TransferFailedException
379    {
380    }
381
382    protected void cleanupGetTransfer( Resource resource )
383    {
384    }
385
386    protected void putTransfer( Resource resource, File source, OutputStream output, boolean closeOutput )
387        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
388    {
389        firePutStarted( resource, source );
390
391        transfer( resource, source, output, closeOutput );
392
393        firePutCompleted( resource, source );
394    }
395
396    /**
397     * Write from {@link File} to {@link OutputStream}
398     *
399     * @param resource    resource to transfer
400     * @param source      file to read from
401     * @param output      output stream
402     * @param closeOutput whether the output stream should be closed or not
403     * @throws TransferFailedException
404     * @throws ResourceDoesNotExistException
405     * @throws AuthorizationException
406     * @since 1.0-beta-1
407     */
408    protected void transfer( Resource resource, File source, OutputStream output, boolean closeOutput )
409        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
410    {
411        InputStream input = null;
412
413        try
414        {
415            input = new FileInputStream( source );
416
417            putTransfer( resource, input, output, closeOutput );
418        }
419        catch ( FileNotFoundException e )
420        {
421            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
422
423            throw new TransferFailedException( "Specified source file does not exist: " + source, e );
424        }
425        finally
426        {
427            IOUtil.close( input );
428        }
429    }
430
431    protected void putTransfer( Resource resource, InputStream input, OutputStream output, boolean closeOutput )
432        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
433    {
434        try
435        {
436            transfer( resource, input, output, TransferEvent.REQUEST_PUT,
437                      resource.getContentLength() == WagonConstants.UNKNOWN_LENGTH
438                          ? Long.MAX_VALUE
439                          : resource.getContentLength() );
440
441            finishPutTransfer( resource, input, output );
442        }
443        catch ( IOException e )
444        {
445            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
446
447            String msg = "PUT request to: " + resource.getName() + " in " + repository.getName() + " failed";
448
449            throw new TransferFailedException( msg, e );
450        }
451        finally
452        {
453            if ( closeOutput )
454            {
455                IOUtil.close( output );
456            }
457
458            cleanupPutTransfer( resource );
459        }
460    }
461
462    protected void cleanupPutTransfer( Resource resource )
463    {
464    }
465
466    protected void finishPutTransfer( Resource resource, InputStream input, OutputStream output )
467        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
468    {
469    }
470
471    /**
472     * Write from {@link InputStream} to {@link OutputStream}.
473     * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, int)} with a maxSize equals to
474     * {@link Integer#MAX_VALUE}
475     *
476     * @param resource    resource to transfer
477     * @param input       input stream
478     * @param output      output stream
479     * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
480     * @throws IOException
481     */
482    protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType )
483        throws IOException
484    {
485        transfer( resource, input, output, requestType, Long.MAX_VALUE );
486    }
487
488    /**
489     * Write from {@link InputStream} to {@link OutputStream}.
490     * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, int)} with a maxSize equals to
491     * {@link Integer#MAX_VALUE}
492     *
493     * @param resource    resource to transfer
494     * @param input       input stream
495     * @param output      output stream
496     * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
497     * @param maxSize     size of the buffer
498     * @throws IOException
499     * @deprecated Please use the transfer using long as type of maxSize
500     */
501    @Deprecated
502    protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType, int maxSize )
503        throws IOException
504    {
505        transfer( resource, input, output, requestType, (long) maxSize );
506    }
507
508    /**
509     * Write from {@link InputStream} to {@link OutputStream}.
510     * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, long)} with a maxSize equals to
511     * {@link Integer#MAX_VALUE}
512     *
513     * @param resource    resource to transfer
514     * @param input       input stream
515     * @param output      output stream
516     * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
517     * @param maxSize     size of the buffer
518     * @throws IOException
519     */
520    protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType, long maxSize )
521        throws IOException
522    {
523        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
524
525        TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_PROGRESS, requestType );
526        transferEvent.setTimestamp( System.currentTimeMillis() );
527
528        long remaining = maxSize;
529        while ( remaining > 0 )
530        {
531            // let's safely cast to int because the min value will be lower than the buffer size.
532            int n = input.read( buffer, 0, (int) Math.min( buffer.length, remaining ) );
533
534            if ( n == -1 )
535            {
536                break;
537            }
538
539            fireTransferProgress( transferEvent, buffer, n );
540
541            output.write( buffer, 0, n );
542
543            remaining -= n;
544        }
545        output.flush();
546    }
547
548    // ----------------------------------------------------------------------
549    //
550    // ----------------------------------------------------------------------
551
552    protected void fireTransferProgress( TransferEvent transferEvent, byte[] buffer, int n )
553    {
554        transferEventSupport.fireTransferProgress( transferEvent, buffer, n );
555    }
556
557    protected void fireGetCompleted( Resource resource, File localFile )
558    {
559        long timestamp = System.currentTimeMillis();
560
561        TransferEvent transferEvent =
562            new TransferEvent( this, resource, TransferEvent.TRANSFER_COMPLETED, TransferEvent.REQUEST_GET );
563
564        transferEvent.setTimestamp( timestamp );
565
566        transferEvent.setLocalFile( localFile );
567
568        transferEventSupport.fireTransferCompleted( transferEvent );
569    }
570
571    protected void fireGetStarted( Resource resource, File localFile )
572    {
573        long timestamp = System.currentTimeMillis();
574
575        TransferEvent transferEvent =
576            new TransferEvent( this, resource, TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_GET );
577
578        transferEvent.setTimestamp( timestamp );
579
580        transferEvent.setLocalFile( localFile );
581
582        transferEventSupport.fireTransferStarted( transferEvent );
583    }
584
585    protected void fireGetInitiated( Resource resource, File localFile )
586    {
587        long timestamp = System.currentTimeMillis();
588
589        TransferEvent transferEvent =
590            new TransferEvent( this, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_GET );
591
592        transferEvent.setTimestamp( timestamp );
593
594        transferEvent.setLocalFile( localFile );
595
596        transferEventSupport.fireTransferInitiated( transferEvent );
597    }
598
599    protected void firePutInitiated( Resource resource, File localFile )
600    {
601        long timestamp = System.currentTimeMillis();
602
603        TransferEvent transferEvent =
604            new TransferEvent( this, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_PUT );
605
606        transferEvent.setTimestamp( timestamp );
607
608        transferEvent.setLocalFile( localFile );
609
610        transferEventSupport.fireTransferInitiated( transferEvent );
611    }
612
613    protected void firePutCompleted( Resource resource, File localFile )
614    {
615        long timestamp = System.currentTimeMillis();
616
617        TransferEvent transferEvent =
618            new TransferEvent( this, resource, TransferEvent.TRANSFER_COMPLETED, TransferEvent.REQUEST_PUT );
619
620        transferEvent.setTimestamp( timestamp );
621
622        transferEvent.setLocalFile( localFile );
623
624        transferEventSupport.fireTransferCompleted( transferEvent );
625    }
626
627    protected void firePutStarted( Resource resource, File localFile )
628    {
629        long timestamp = System.currentTimeMillis();
630
631        TransferEvent transferEvent =
632            new TransferEvent( this, resource, TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_PUT );
633
634        transferEvent.setTimestamp( timestamp );
635
636        transferEvent.setLocalFile( localFile );
637
638        transferEventSupport.fireTransferStarted( transferEvent );
639    }
640
641    protected void fireSessionDisconnected()
642    {
643        long timestamp = System.currentTimeMillis();
644
645        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_DISCONNECTED );
646
647        sessionEvent.setTimestamp( timestamp );
648
649        sessionEventSupport.fireSessionDisconnected( sessionEvent );
650    }
651
652    protected void fireSessionDisconnecting()
653    {
654        long timestamp = System.currentTimeMillis();
655
656        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_DISCONNECTING );
657
658        sessionEvent.setTimestamp( timestamp );
659
660        sessionEventSupport.fireSessionDisconnecting( sessionEvent );
661    }
662
663    protected void fireSessionLoggedIn()
664    {
665        long timestamp = System.currentTimeMillis();
666
667        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_LOGGED_IN );
668
669        sessionEvent.setTimestamp( timestamp );
670
671        sessionEventSupport.fireSessionLoggedIn( sessionEvent );
672    }
673
674    protected void fireSessionLoggedOff()
675    {
676        long timestamp = System.currentTimeMillis();
677
678        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_LOGGED_OFF );
679
680        sessionEvent.setTimestamp( timestamp );
681
682        sessionEventSupport.fireSessionLoggedOff( sessionEvent );
683    }
684
685    protected void fireSessionOpened()
686    {
687        long timestamp = System.currentTimeMillis();
688
689        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_OPENED );
690
691        sessionEvent.setTimestamp( timestamp );
692
693        sessionEventSupport.fireSessionOpened( sessionEvent );
694    }
695
696    protected void fireSessionOpening()
697    {
698        long timestamp = System.currentTimeMillis();
699
700        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_OPENING );
701
702        sessionEvent.setTimestamp( timestamp );
703
704        sessionEventSupport.fireSessionOpening( sessionEvent );
705    }
706
707    protected void fireSessionConnectionRefused()
708    {
709        long timestamp = System.currentTimeMillis();
710
711        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_CONNECTION_REFUSED );
712
713        sessionEvent.setTimestamp( timestamp );
714
715        sessionEventSupport.fireSessionConnectionRefused( sessionEvent );
716    }
717
718    protected void fireSessionError( Exception exception )
719    {
720        long timestamp = System.currentTimeMillis();
721
722        SessionEvent sessionEvent = new SessionEvent( this, exception );
723
724        sessionEvent.setTimestamp( timestamp );
725
726        sessionEventSupport.fireSessionError( sessionEvent );
727
728    }
729
730    protected void fireTransferDebug( String message )
731    {
732        transferEventSupport.fireDebug( message );
733    }
734
735    protected void fireSessionDebug( String message )
736    {
737        sessionEventSupport.fireDebug( message );
738    }
739
740    public boolean hasTransferListener( TransferListener listener )
741    {
742        return transferEventSupport.hasTransferListener( listener );
743    }
744
745    public void addTransferListener( TransferListener listener )
746    {
747        transferEventSupport.addTransferListener( listener );
748    }
749
750    public void removeTransferListener( TransferListener listener )
751    {
752        transferEventSupport.removeTransferListener( listener );
753    }
754
755    public void addSessionListener( SessionListener listener )
756    {
757        sessionEventSupport.addSessionListener( listener );
758    }
759
760    public boolean hasSessionListener( SessionListener listener )
761    {
762        return sessionEventSupport.hasSessionListener( listener );
763    }
764
765    public void removeSessionListener( SessionListener listener )
766    {
767        sessionEventSupport.removeSessionListener( listener );
768    }
769
770    protected void fireTransferError( Resource resource, Exception e, int requestType )
771    {
772        TransferEvent transferEvent = new TransferEvent( this, resource, e, requestType );
773        transferEventSupport.fireTransferError( transferEvent );
774    }
775
776
777    public SessionEventSupport getSessionEventSupport()
778    {
779        return sessionEventSupport;
780    }
781
782    public void setSessionEventSupport( SessionEventSupport sessionEventSupport )
783    {
784        this.sessionEventSupport = sessionEventSupport;
785    }
786
787    public TransferEventSupport getTransferEventSupport()
788    {
789        return transferEventSupport;
790    }
791
792    public void setTransferEventSupport( TransferEventSupport transferEventSupport )
793    {
794        this.transferEventSupport = transferEventSupport;
795    }
796
797    /**
798     * This method is used if you are not streaming the transfer, to make sure any listeners dependent on state
799     * (eg checksum observers) succeed.
800     */
801    protected void postProcessListeners( Resource resource, File source, int requestType )
802        throws TransferFailedException
803    {
804        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
805
806        TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_PROGRESS, requestType );
807        transferEvent.setTimestamp( System.currentTimeMillis() );
808        transferEvent.setLocalFile( source );
809
810        InputStream input = null;
811        try
812        {
813            input = new FileInputStream( source );
814
815            while ( true )
816            {
817                int n = input.read( buffer );
818
819                if ( n == -1 )
820                {
821                    break;
822                }
823
824                fireTransferProgress( transferEvent, buffer, n );
825            }
826        }
827        catch ( IOException e )
828        {
829            fireTransferError( resource, e, requestType );
830
831            throw new TransferFailedException( "Failed to post-process the source file", e );
832        }
833        finally
834        {
835            IOUtil.close( input );
836        }
837    }
838
839    public void putDirectory( File sourceDirectory, String destinationDirectory )
840        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
841    {
842        throw new UnsupportedOperationException( "The wagon you are using has not implemented putDirectory()" );
843    }
844
845    public boolean supportsDirectoryCopy()
846    {
847        return false;
848    }
849
850    protected static String getPath( String basedir, String dir )
851    {
852        String path;
853        path = basedir;
854        if ( !basedir.endsWith( "/" ) && !dir.startsWith( "/" ) )
855        {
856            path += "/";
857        }
858        path += dir;
859        return path;
860    }
861
862    public boolean isInteractive()
863    {
864        return interactive;
865    }
866
867    public void setInteractive( boolean interactive )
868    {
869        this.interactive = interactive;
870    }
871
872    public List<String> getFileList( String destinationDirectory )
873        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
874    {
875        throw new UnsupportedOperationException( "The wagon you are using has not implemented getFileList()" );
876    }
877
878    public boolean resourceExists( String resourceName )
879        throws TransferFailedException, AuthorizationException
880    {
881        throw new UnsupportedOperationException( "The wagon you are using has not implemented resourceExists()" );
882    }
883
884    protected ProxyInfo getProxyInfo( String protocol, String host )
885    {
886        if ( proxyInfoProvider != null )
887        {
888            ProxyInfo proxyInfo = proxyInfoProvider.getProxyInfo( protocol );
889            if ( !ProxyUtils.validateNonProxyHosts( proxyInfo, host ) )
890            {
891                return proxyInfo;
892            }
893        }
894        return null;
895    }
896
897    public RepositoryPermissions getPermissionsOverride()
898    {
899        return permissionsOverride;
900    }
901
902    public void setPermissionsOverride( RepositoryPermissions permissionsOverride )
903    {
904        this.permissionsOverride = permissionsOverride;
905    }
906
907    public void setReadTimeout( int readTimeout )
908    {
909        this.readTimeout = readTimeout;
910    }
911
912    public int getReadTimeout()
913    {
914        return this.readTimeout;
915    }
916}