View Javadoc

1   package org.apache.maven.wagon;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.wagon.authentication.AuthenticationException;
23  import org.apache.maven.wagon.authentication.AuthenticationInfo;
24  import org.apache.maven.wagon.authorization.AuthorizationException;
25  import org.apache.maven.wagon.events.SessionEvent;
26  import org.apache.maven.wagon.events.SessionEventSupport;
27  import org.apache.maven.wagon.events.SessionListener;
28  import org.apache.maven.wagon.events.TransferEvent;
29  import org.apache.maven.wagon.events.TransferEventSupport;
30  import org.apache.maven.wagon.events.TransferListener;
31  import org.apache.maven.wagon.proxy.ProxyInfo;
32  import org.apache.maven.wagon.proxy.ProxyInfoProvider;
33  import org.apache.maven.wagon.proxy.ProxyUtils;
34  import org.apache.maven.wagon.repository.Repository;
35  import org.apache.maven.wagon.repository.RepositoryPermissions;
36  import org.apache.maven.wagon.resource.Resource;
37  import org.codehaus.plexus.util.IOUtil;
38  
39  import java.io.File;
40  import java.io.FileInputStream;
41  import java.io.FileNotFoundException;
42  import java.io.IOException;
43  import java.io.InputStream;
44  import java.io.OutputStream;
45  import java.util.List;
46  
47  /**
48   * Implementation of common facilities for Wagon providers.
49   *
50   * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
51   */
52  public abstract class AbstractWagon
53      implements Wagon
54  {
55      protected static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
56  
57      protected Repository repository;
58  
59      protected SessionEventSupport sessionEventSupport = new SessionEventSupport();
60  
61      protected TransferEventSupport transferEventSupport = new TransferEventSupport();
62  
63      protected AuthenticationInfo authenticationInfo;
64  
65      protected boolean interactive = true;
66  
67  
68      private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
69  
70      /**
71       * read timeout value
72       *
73       * @since 2.2
74       */
75      private int readTimeout =
76          Integer.parseInt( System.getProperty( "maven.wagon.rto", Integer.toString( Wagon.DEFAULT_READ_TIMEOUT ) ) );
77  
78      private ProxyInfoProvider proxyInfoProvider;
79  
80      /**
81       * @deprecated
82       */
83      protected ProxyInfo proxyInfo;
84  
85      private RepositoryPermissions permissionsOverride;
86  
87      // ----------------------------------------------------------------------
88      // Accessors
89      // ----------------------------------------------------------------------
90  
91      public Repository getRepository()
92      {
93          return repository;
94      }
95  
96      public ProxyInfo getProxyInfo()
97      {
98          return proxyInfoProvider != null ? proxyInfoProvider.getProxyInfo( null ) : null;
99      }
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 }