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    }
174
175    public void connect( Repository repository, AuthenticationInfo authenticationInfo,
176                         ProxyInfoProvider proxyInfoProvider )
177        throws ConnectionException, AuthenticationException
178    {
179        if ( repository == null )
180        {
181            throw new IllegalStateException( "The repository specified cannot be null." );
182        }
183
184        if ( permissionsOverride != null )
185        {
186            repository.setPermissions( permissionsOverride );
187        }
188
189        this.repository = repository;
190
191        if ( authenticationInfo == null )
192        {
193            authenticationInfo = new AuthenticationInfo();
194        }
195
196        if ( authenticationInfo.getUserName() == null )
197        {
198            // Get user/pass that were encoded in the URL.
199            if ( repository.getUsername() != null )
200            {
201                authenticationInfo.setUserName( repository.getUsername() );
202                if ( repository.getPassword() != null && authenticationInfo.getPassword() == null )
203                {
204                    authenticationInfo.setPassword( repository.getPassword() );
205                }
206            }
207        }
208
209        // TODO: Do these needs to be fields, or are they only used in openConnection()?
210        this.authenticationInfo = authenticationInfo;
211
212        this.proxyInfoProvider = proxyInfoProvider;
213
214        fireSessionOpening();
215
216        openConnection();
217
218        fireSessionOpened();
219    }
220
221    protected abstract void openConnectionInternal()
222        throws ConnectionException, AuthenticationException;
223
224    public void disconnect()
225        throws ConnectionException
226    {
227        fireSessionDisconnecting();
228
229        try
230        {
231            closeConnection();
232        }
233        catch ( ConnectionException e )
234        {
235            fireSessionError( e );
236            throw e;
237        }
238
239        fireSessionDisconnected();
240    }
241
242    protected abstract void closeConnection()
243        throws ConnectionException;
244
245    protected void createParentDirectories( File destination )
246        throws TransferFailedException
247    {
248        File destinationDirectory = destination.getParentFile();
249        try
250        {
251            destinationDirectory = destinationDirectory.getCanonicalFile();
252        }
253        catch ( IOException e )
254        {
255            // not essential to have a canonical file
256        }
257        if ( destinationDirectory != null && !destinationDirectory.exists() )
258        {
259            destinationDirectory.mkdirs();
260            if ( !destinationDirectory.exists() )
261            {
262                throw new TransferFailedException(
263                    "Specified destination directory cannot be created: " + destinationDirectory );
264            }
265        }
266    }
267
268    public void setTimeout( int timeoutValue )
269    {
270        connectionTimeout = timeoutValue;
271    }
272
273    public int getTimeout()
274    {
275        return connectionTimeout;
276    }
277
278    // ----------------------------------------------------------------------
279    // Stream i/o
280    // ----------------------------------------------------------------------
281
282    protected void getTransfer( Resource resource, File destination, InputStream input )
283        throws TransferFailedException
284    {
285        getTransfer( resource, destination, input, true, Long.MAX_VALUE );
286    }
287
288    protected void getTransfer( Resource resource, OutputStream output, InputStream input )
289        throws TransferFailedException
290    {
291        getTransfer( resource, output, input, true, Long.MAX_VALUE );
292    }
293
294    @Deprecated
295    protected void getTransfer( Resource resource, File destination, InputStream input, boolean closeInput,
296                                int maxSize )
297        throws TransferFailedException
298    {
299        getTransfer( resource, destination, input, closeInput, (long) maxSize );
300    }
301
302    protected void getTransfer( Resource resource, File destination, InputStream input, boolean closeInput,
303                                long maxSize )
304        throws TransferFailedException
305    {
306        // ensure that the destination is created only when we are ready to transfer
307        fireTransferDebug( "attempting to create parent directories for destination: " + destination.getName() );
308        createParentDirectories( destination );
309
310        OutputStream output = new LazyFileOutputStream( destination );
311
312        fireGetStarted( resource, destination );
313
314        try
315        {
316            getTransfer( resource, output, input, closeInput, maxSize );
317        }
318        catch ( TransferFailedException e )
319        {
320            if ( destination.exists() )
321            {
322                boolean deleted = destination.delete();
323
324                if ( !deleted )
325                {
326                    destination.deleteOnExit();
327                }
328            }
329            throw e;
330        }
331        finally
332        {
333            IOUtil.close( output );
334        }
335
336        fireGetCompleted( resource, destination );
337    }
338
339    @Deprecated
340    protected void getTransfer( Resource resource, OutputStream output, InputStream input, boolean closeInput,
341                                int maxSize )
342        throws TransferFailedException
343    {
344        getTransfer( resource, output, input, closeInput, (long) maxSize );
345    }
346
347    protected void getTransfer( Resource resource, OutputStream output, InputStream input, boolean closeInput,
348                                long maxSize )
349        throws TransferFailedException
350    {
351        try
352        {
353            transfer( resource, input, output, TransferEvent.REQUEST_GET, maxSize );
354
355            finishGetTransfer( resource, input, output );
356        }
357        catch ( IOException e )
358        {
359            fireTransferError( resource, e, TransferEvent.REQUEST_GET );
360
361            String msg = "GET request of: " + resource.getName() + " from " + repository.getName() + " failed";
362
363            throw new TransferFailedException( msg, e );
364        }
365        finally
366        {
367            if ( closeInput )
368            {
369                IOUtil.close( input );
370            }
371
372            cleanupGetTransfer( resource );
373        }
374    }
375
376    protected void finishGetTransfer( Resource resource, InputStream input, OutputStream output )
377        throws TransferFailedException
378    {
379    }
380
381    protected void cleanupGetTransfer( Resource resource )
382    {
383    }
384
385    protected void putTransfer( Resource resource, File source, OutputStream output, boolean closeOutput )
386        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
387    {
388        firePutStarted( resource, source );
389
390        transfer( resource, source, output, closeOutput );
391
392        firePutCompleted( resource, source );
393    }
394
395    /**
396     * Write from {@link File} to {@link OutputStream}
397     *
398     * @param resource    resource to transfer
399     * @param source      file to read from
400     * @param output      output stream
401     * @param closeOutput whether the output stream should be closed or not
402     * @throws TransferFailedException
403     * @throws ResourceDoesNotExistException
404     * @throws AuthorizationException
405     * @since 1.0-beta-1
406     */
407    protected void transfer( Resource resource, File source, OutputStream output, boolean closeOutput )
408        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
409    {
410        InputStream input = null;
411
412        try
413        {
414            input = new FileInputStream( source );
415
416            putTransfer( resource, input, output, closeOutput );
417        }
418        catch ( FileNotFoundException e )
419        {
420            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
421
422            throw new TransferFailedException( "Specified source file does not exist: " + source, e );
423        }
424        finally
425        {
426            IOUtil.close( input );
427        }
428    }
429
430    protected void putTransfer( Resource resource, InputStream input, OutputStream output, boolean closeOutput )
431        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
432    {
433        try
434        {
435            transfer( resource, input, output, TransferEvent.REQUEST_PUT,
436                      resource.getContentLength() == WagonConstants.UNKNOWN_LENGTH
437                          ? Long.MAX_VALUE
438                          : resource.getContentLength() );
439
440            finishPutTransfer( resource, input, output );
441        }
442        catch ( IOException e )
443        {
444            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
445
446            String msg = "PUT request to: " + resource.getName() + " in " + repository.getName() + " failed";
447
448            throw new TransferFailedException( msg, e );
449        }
450        finally
451        {
452            if ( closeOutput )
453            {
454                IOUtil.close( output );
455            }
456
457            cleanupPutTransfer( resource );
458        }
459    }
460
461    protected void cleanupPutTransfer( Resource resource )
462    {
463    }
464
465    protected void finishPutTransfer( Resource resource, InputStream input, OutputStream output )
466        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
467    {
468    }
469
470    /**
471     * Write from {@link InputStream} to {@link OutputStream}.
472     * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, int)} with a maxSize equals to
473     * {@link Integer#MAX_VALUE}
474     *
475     * @param resource    resource to transfer
476     * @param input       input stream
477     * @param output      output stream
478     * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
479     * @throws IOException
480     */
481    protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType )
482        throws IOException
483    {
484        transfer( resource, input, output, requestType, Long.MAX_VALUE );
485    }
486
487    /**
488     * Write from {@link InputStream} to {@link OutputStream}.
489     * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, int)} with a maxSize equals to
490     * {@link Integer#MAX_VALUE}
491     *
492     * @param resource    resource to transfer
493     * @param input       input stream
494     * @param output      output stream
495     * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
496     * @param maxSize     size of the buffer
497     * @throws IOException
498     * @deprecated Please use the transfer using long as type of maxSize
499     */
500    @Deprecated
501    protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType, int maxSize )
502        throws IOException
503    {
504        transfer( resource, input, output, requestType, (long) maxSize );
505    }
506
507    /**
508     * Write from {@link InputStream} to {@link OutputStream}.
509     * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, long)} with a maxSize equals to
510     * {@link Integer#MAX_VALUE}
511     *
512     * @param resource    resource to transfer
513     * @param input       input stream
514     * @param output      output stream
515     * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
516     * @param maxSize     size of the buffer
517     * @throws IOException
518     */
519    protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType, long maxSize )
520        throws IOException
521    {
522        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
523
524        TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_PROGRESS, requestType );
525        transferEvent.setTimestamp( System.currentTimeMillis() );
526
527        long remaining = maxSize;
528        while ( remaining > 0 )
529        {
530            // let's safely cast to int because the min value will be lower than the buffer size.
531            int n = input.read( buffer, 0, (int) Math.min( buffer.length, remaining ) );
532
533            if ( n == -1 )
534            {
535                break;
536            }
537
538            fireTransferProgress( transferEvent, buffer, n );
539
540            output.write( buffer, 0, n );
541
542            remaining -= n;
543        }
544        output.flush();
545    }
546
547    // ----------------------------------------------------------------------
548    //
549    // ----------------------------------------------------------------------
550
551    protected void fireTransferProgress( TransferEvent transferEvent, byte[] buffer, int n )
552    {
553        transferEventSupport.fireTransferProgress( transferEvent, buffer, n );
554    }
555
556    protected void fireGetCompleted( Resource resource, File localFile )
557    {
558        long timestamp = System.currentTimeMillis();
559
560        TransferEvent transferEvent =
561            new TransferEvent( this, resource, TransferEvent.TRANSFER_COMPLETED, TransferEvent.REQUEST_GET );
562
563        transferEvent.setTimestamp( timestamp );
564
565        transferEvent.setLocalFile( localFile );
566
567        transferEventSupport.fireTransferCompleted( transferEvent );
568    }
569
570    protected void fireGetStarted( Resource resource, File localFile )
571    {
572        long timestamp = System.currentTimeMillis();
573
574        TransferEvent transferEvent =
575            new TransferEvent( this, resource, TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_GET );
576
577        transferEvent.setTimestamp( timestamp );
578
579        transferEvent.setLocalFile( localFile );
580
581        transferEventSupport.fireTransferStarted( transferEvent );
582    }
583
584    protected void fireGetInitiated( Resource resource, File localFile )
585    {
586        long timestamp = System.currentTimeMillis();
587
588        TransferEvent transferEvent =
589            new TransferEvent( this, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_GET );
590
591        transferEvent.setTimestamp( timestamp );
592
593        transferEvent.setLocalFile( localFile );
594
595        transferEventSupport.fireTransferInitiated( transferEvent );
596    }
597
598    protected void firePutInitiated( Resource resource, File localFile )
599    {
600        long timestamp = System.currentTimeMillis();
601
602        TransferEvent transferEvent =
603            new TransferEvent( this, resource, TransferEvent.TRANSFER_INITIATED, TransferEvent.REQUEST_PUT );
604
605        transferEvent.setTimestamp( timestamp );
606
607        transferEvent.setLocalFile( localFile );
608
609        transferEventSupport.fireTransferInitiated( transferEvent );
610    }
611
612    protected void firePutCompleted( Resource resource, File localFile )
613    {
614        long timestamp = System.currentTimeMillis();
615
616        TransferEvent transferEvent =
617            new TransferEvent( this, resource, TransferEvent.TRANSFER_COMPLETED, TransferEvent.REQUEST_PUT );
618
619        transferEvent.setTimestamp( timestamp );
620
621        transferEvent.setLocalFile( localFile );
622
623        transferEventSupport.fireTransferCompleted( transferEvent );
624    }
625
626    protected void firePutStarted( Resource resource, File localFile )
627    {
628        long timestamp = System.currentTimeMillis();
629
630        TransferEvent transferEvent =
631            new TransferEvent( this, resource, TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_PUT );
632
633        transferEvent.setTimestamp( timestamp );
634
635        transferEvent.setLocalFile( localFile );
636
637        transferEventSupport.fireTransferStarted( transferEvent );
638    }
639
640    protected void fireSessionDisconnected()
641    {
642        long timestamp = System.currentTimeMillis();
643
644        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_DISCONNECTED );
645
646        sessionEvent.setTimestamp( timestamp );
647
648        sessionEventSupport.fireSessionDisconnected( sessionEvent );
649    }
650
651    protected void fireSessionDisconnecting()
652    {
653        long timestamp = System.currentTimeMillis();
654
655        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_DISCONNECTING );
656
657        sessionEvent.setTimestamp( timestamp );
658
659        sessionEventSupport.fireSessionDisconnecting( sessionEvent );
660    }
661
662    protected void fireSessionLoggedIn()
663    {
664        long timestamp = System.currentTimeMillis();
665
666        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_LOGGED_IN );
667
668        sessionEvent.setTimestamp( timestamp );
669
670        sessionEventSupport.fireSessionLoggedIn( sessionEvent );
671    }
672
673    protected void fireSessionLoggedOff()
674    {
675        long timestamp = System.currentTimeMillis();
676
677        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_LOGGED_OFF );
678
679        sessionEvent.setTimestamp( timestamp );
680
681        sessionEventSupport.fireSessionLoggedOff( sessionEvent );
682    }
683
684    protected void fireSessionOpened()
685    {
686        long timestamp = System.currentTimeMillis();
687
688        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_OPENED );
689
690        sessionEvent.setTimestamp( timestamp );
691
692        sessionEventSupport.fireSessionOpened( sessionEvent );
693    }
694
695    protected void fireSessionOpening()
696    {
697        long timestamp = System.currentTimeMillis();
698
699        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_OPENING );
700
701        sessionEvent.setTimestamp( timestamp );
702
703        sessionEventSupport.fireSessionOpening( sessionEvent );
704    }
705
706    protected void fireSessionConnectionRefused()
707    {
708        long timestamp = System.currentTimeMillis();
709
710        SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_CONNECTION_REFUSED );
711
712        sessionEvent.setTimestamp( timestamp );
713
714        sessionEventSupport.fireSessionConnectionRefused( sessionEvent );
715    }
716
717    protected void fireSessionError( Exception exception )
718    {
719        long timestamp = System.currentTimeMillis();
720
721        SessionEvent sessionEvent = new SessionEvent( this, exception );
722
723        sessionEvent.setTimestamp( timestamp );
724
725        sessionEventSupport.fireSessionError( sessionEvent );
726
727    }
728
729    protected void fireTransferDebug( String message )
730    {
731        transferEventSupport.fireDebug( message );
732    }
733
734    protected void fireSessionDebug( String message )
735    {
736        sessionEventSupport.fireDebug( message );
737    }
738
739    public boolean hasTransferListener( TransferListener listener )
740    {
741        return transferEventSupport.hasTransferListener( listener );
742    }
743
744    public void addTransferListener( TransferListener listener )
745    {
746        transferEventSupport.addTransferListener( listener );
747    }
748
749    public void removeTransferListener( TransferListener listener )
750    {
751        transferEventSupport.removeTransferListener( listener );
752    }
753
754    public void addSessionListener( SessionListener listener )
755    {
756        sessionEventSupport.addSessionListener( listener );
757    }
758
759    public boolean hasSessionListener( SessionListener listener )
760    {
761        return sessionEventSupport.hasSessionListener( listener );
762    }
763
764    public void removeSessionListener( SessionListener listener )
765    {
766        sessionEventSupport.removeSessionListener( listener );
767    }
768
769    protected void fireTransferError( Resource resource, Exception e, int requestType )
770    {
771        TransferEvent transferEvent = new TransferEvent( this, resource, e, requestType );
772        transferEventSupport.fireTransferError( transferEvent );
773    }
774
775
776    public SessionEventSupport getSessionEventSupport()
777    {
778        return sessionEventSupport;
779    }
780
781    public void setSessionEventSupport( SessionEventSupport sessionEventSupport )
782    {
783        this.sessionEventSupport = sessionEventSupport;
784    }
785
786    public TransferEventSupport getTransferEventSupport()
787    {
788        return transferEventSupport;
789    }
790
791    public void setTransferEventSupport( TransferEventSupport transferEventSupport )
792    {
793        this.transferEventSupport = transferEventSupport;
794    }
795
796    /**
797     * This method is used if you are not streaming the transfer, to make sure any listeners dependent on state
798     * (eg checksum observers) succeed.
799     */
800    protected void postProcessListeners( Resource resource, File source, int requestType )
801        throws TransferFailedException
802    {
803        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
804
805        TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_PROGRESS, requestType );
806        transferEvent.setTimestamp( System.currentTimeMillis() );
807        transferEvent.setLocalFile( source );
808
809        InputStream input = null;
810        try
811        {
812            input = new FileInputStream( source );
813
814            while ( true )
815            {
816                int n = input.read( buffer );
817
818                if ( n == -1 )
819                {
820                    break;
821                }
822
823                fireTransferProgress( transferEvent, buffer, n );
824            }
825        }
826        catch ( IOException e )
827        {
828            fireTransferError( resource, e, requestType );
829
830            throw new TransferFailedException( "Failed to post-process the source file", e );
831        }
832        finally
833        {
834            IOUtil.close( input );
835        }
836    }
837
838    public void putDirectory( File sourceDirectory, String destinationDirectory )
839        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
840    {
841        throw new UnsupportedOperationException( "The wagon you are using has not implemented putDirectory()" );
842    }
843
844    public boolean supportsDirectoryCopy()
845    {
846        return false;
847    }
848
849    protected static String getPath( String basedir, String dir )
850    {
851        String path;
852        path = basedir;
853        if ( !basedir.endsWith( "/" ) && !dir.startsWith( "/" ) )
854        {
855            path += "/";
856        }
857        path += dir;
858        return path;
859    }
860
861    public boolean isInteractive()
862    {
863        return interactive;
864    }
865
866    public void setInteractive( boolean interactive )
867    {
868        this.interactive = interactive;
869    }
870
871    public List<String> getFileList( String destinationDirectory )
872        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
873    {
874        throw new UnsupportedOperationException( "The wagon you are using has not implemented getFileList()" );
875    }
876
877    public boolean resourceExists( String resourceName )
878        throws TransferFailedException, AuthorizationException
879    {
880        throw new UnsupportedOperationException( "The wagon you are using has not implemented resourceExists()" );
881    }
882
883    protected ProxyInfo getProxyInfo( String protocol, String host )
884    {
885        if ( proxyInfoProvider != null )
886        {
887            ProxyInfo proxyInfo = proxyInfoProvider.getProxyInfo( protocol );
888            if ( !ProxyUtils.validateNonProxyHosts( proxyInfo, host ) )
889            {
890                return proxyInfo;
891            }
892        }
893        return null;
894    }
895
896    public RepositoryPermissions getPermissionsOverride()
897    {
898        return permissionsOverride;
899    }
900
901    public void setPermissionsOverride( RepositoryPermissions permissionsOverride )
902    {
903        this.permissionsOverride = permissionsOverride;
904    }
905
906    public void setReadTimeout( int readTimeout )
907    {
908        this.readTimeout = readTimeout;
909    }
910
911    public int getReadTimeout()
912    {
913        return this.readTimeout;
914    }
915}