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 java.io.File;
23  import java.io.FileInputStream;
24  import java.io.FileNotFoundException;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.OutputStream;
28  import java.util.List;
29  
30  import org.apache.maven.wagon.authentication.AuthenticationException;
31  import org.apache.maven.wagon.authentication.AuthenticationInfo;
32  import org.apache.maven.wagon.authorization.AuthorizationException;
33  import org.apache.maven.wagon.events.SessionEvent;
34  import org.apache.maven.wagon.events.SessionEventSupport;
35  import org.apache.maven.wagon.events.SessionListener;
36  import org.apache.maven.wagon.events.TransferEvent;
37  import org.apache.maven.wagon.events.TransferEventSupport;
38  import org.apache.maven.wagon.events.TransferListener;
39  import org.apache.maven.wagon.proxy.ProxyInfo;
40  import org.apache.maven.wagon.proxy.ProxyInfoProvider;
41  import org.apache.maven.wagon.proxy.ProxyUtils;
42  import org.apache.maven.wagon.repository.Repository;
43  import org.apache.maven.wagon.repository.RepositoryPermissions;
44  import org.apache.maven.wagon.resource.Resource;
45  import org.codehaus.plexus.util.IOUtil;
46  
47  /**
48   * Implementation of common facilities for Wagon providers.
49   *
50   * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
51   * @version $Id: AbstractWagon.java 682051 2008-08-02 21:29:38Z hboutemy $
52   */
53  public abstract class AbstractWagon
54      implements Wagon
55  {
56      protected static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
57  
58      protected Repository repository;
59  
60      protected SessionEventSupport sessionEventSupport = new SessionEventSupport();
61  
62      protected TransferEventSupport transferEventSupport = new TransferEventSupport();
63  
64      protected AuthenticationInfo authenticationInfo;
65  
66      protected boolean interactive = true;
67      
68      private int connectionTimeout = 60000;
69      
70      private ProxyInfoProvider proxyInfoProvider;
71      
72      /** @deprecated */
73      protected ProxyInfo proxyInfo;
74      
75      private RepositoryPermissions permissionsOverride;
76  
77      // ----------------------------------------------------------------------
78      // Accessors
79      // ----------------------------------------------------------------------
80  
81      public Repository getRepository()
82      {
83          return repository;
84      }
85  
86      public ProxyInfo getProxyInfo()
87      {
88          return proxyInfoProvider != null ? proxyInfoProvider.getProxyInfo( null ) : null;
89      }
90  
91      public AuthenticationInfo getAuthenticationInfo()
92      {
93          return authenticationInfo;
94      }
95  
96      // ----------------------------------------------------------------------
97      // Connection
98      // ----------------------------------------------------------------------
99  
100     public void openConnection()
101         throws ConnectionException, AuthenticationException
102     {
103         try
104         {
105             openConnectionInternal();
106         }
107         catch ( ConnectionException e )
108         {
109             fireSessionConnectionRefused();
110             
111             throw e;
112         }
113         catch ( AuthenticationException e )
114         {
115             fireSessionConnectionRefused();
116             
117             throw e;
118         }
119     }
120 
121     public void connect( Repository repository )
122         throws ConnectionException, AuthenticationException
123     {
124         connect( repository, null, (ProxyInfoProvider) null );
125     }
126 
127     public void connect( Repository repository, ProxyInfo proxyInfo )
128         throws ConnectionException, AuthenticationException
129     {
130         connect( repository, null, proxyInfo );
131     }
132 
133     public void connect( Repository repository, ProxyInfoProvider proxyInfoProvider )
134         throws ConnectionException, AuthenticationException
135     {
136         connect( repository, null, proxyInfoProvider );
137     }
138 
139     public void connect( Repository repository, AuthenticationInfo authenticationInfo )
140         throws ConnectionException, AuthenticationException
141     {
142         connect( repository, authenticationInfo, (ProxyInfoProvider) null );
143     }
144 
145     public void connect( Repository repository, AuthenticationInfo authenticationInfo, ProxyInfo proxyInfo )
146         throws ConnectionException, AuthenticationException
147     {
148         final ProxyInfo proxy = proxyInfo;
149         connect( repository, authenticationInfo, new ProxyInfoProvider()
150         {
151             public ProxyInfo getProxyInfo( String protocol )
152             {
153                 if ( protocol == null || proxy == null || protocol.equalsIgnoreCase( proxy.getType() ) )
154                 {
155                     return proxy;
156                 }
157                 else
158                 {
159                     return null;
160                 }
161             }
162         } );
163         this.proxyInfo = proxyInfo;
164     }
165     
166     public void connect( Repository repository, AuthenticationInfo authenticationInfo,
167                          ProxyInfoProvider proxyInfoProvider )
168         throws ConnectionException, AuthenticationException
169     {
170         if ( repository == null )
171         {
172             throw new IllegalStateException( "The repository specified cannot be null." );
173         }
174 
175         if ( permissionsOverride != null )
176         {
177             repository.setPermissions( permissionsOverride );
178         }
179         
180         this.repository = repository;
181 
182         if ( authenticationInfo == null )
183         {
184             authenticationInfo = new AuthenticationInfo();
185         }
186 
187         if ( authenticationInfo.getUserName() == null )
188         {
189             // Get user/pass that were encoded in the URL.
190             if ( repository.getUsername() != null )
191             {
192                 authenticationInfo.setUserName( repository.getUsername() );
193                 if ( repository.getPassword() != null && authenticationInfo.getPassword() == null )
194                 {
195                     authenticationInfo.setPassword( repository.getPassword() );
196                 }
197             }
198         }
199 
200         // TODO: Do these needs to be fields, or are they only used in openConnection()?
201         this.authenticationInfo = authenticationInfo;
202         
203         this.proxyInfoProvider = proxyInfoProvider;
204         
205         fireSessionOpening();
206 
207         openConnection();
208 
209         fireSessionOpened();
210     }
211 
212     protected abstract void openConnectionInternal()
213         throws ConnectionException, AuthenticationException;
214 
215     public void disconnect()
216         throws ConnectionException
217     {
218         fireSessionDisconnecting();
219 
220         try
221         {
222             closeConnection();
223         }
224         catch ( ConnectionException e )
225         {
226             fireSessionError( e );
227             throw e;
228         }
229 
230         fireSessionDisconnected();
231     }
232 
233     protected abstract void closeConnection()
234         throws ConnectionException;
235 
236     protected void createParentDirectories( File destination )
237         throws TransferFailedException
238     {
239         File destinationDirectory = destination.getParentFile();
240         try
241         {
242             destinationDirectory = destinationDirectory.getCanonicalFile();
243         }
244         catch ( IOException e )
245         {
246             // not essential to have a canonical file
247         }
248         if ( destinationDirectory != null && !destinationDirectory.exists() )
249         {
250             destinationDirectory.mkdirs();
251             if ( !destinationDirectory.exists() )
252             {
253                 throw new TransferFailedException(
254                     "Specified destination directory cannot be created: " + destinationDirectory );
255             }
256         }
257     }
258     
259     public void setTimeout( int timeoutValue )
260     {
261         connectionTimeout = timeoutValue;
262     }
263     
264     public int getTimeout()
265     {
266         return connectionTimeout;
267     }
268 
269     // ----------------------------------------------------------------------
270     // Stream i/o
271     // ----------------------------------------------------------------------
272 
273     protected void getTransfer( Resource resource, File destination, InputStream input )
274         throws TransferFailedException
275     {
276         getTransfer( resource, destination, input, true, Integer.MAX_VALUE );
277     }
278 
279     protected void getTransfer( Resource resource, OutputStream output, InputStream input )
280         throws TransferFailedException
281     {
282         getTransfer( resource, output, input, true, Integer.MAX_VALUE );
283     }
284 
285     protected void getTransfer( Resource resource, File destination, InputStream input, boolean closeInput,
286                                 int maxSize )
287         throws TransferFailedException
288     {
289         // ensure that the destination is created only when we are ready to transfer
290         fireTransferDebug( "attempting to create parent directories for destination: " + destination.getName() );
291         createParentDirectories( destination );
292 
293         OutputStream output = new LazyFileOutputStream( destination );
294 
295         fireGetStarted( resource, destination );
296 
297         try
298         {
299             getTransfer( resource, output, input, closeInput, maxSize );
300         }
301         catch ( TransferFailedException e )
302         {
303             if ( destination.exists() )
304             {
305                 boolean deleted = destination.delete();
306 
307                 if ( !deleted )
308                 {
309                     destination.deleteOnExit();
310                 }
311             }
312             throw e;
313         }
314         finally
315         {
316             IOUtil.close( output );
317         }
318 
319         fireGetCompleted( resource, destination );
320     }
321 
322     protected void getTransfer( Resource resource, OutputStream output, InputStream input, boolean closeInput,
323                                 int maxSize )
324         throws TransferFailedException
325     {
326         try
327         {
328             transfer( resource, input, output, TransferEvent.REQUEST_GET, maxSize );
329             
330             finishGetTransfer( resource, input, output );
331         }
332         catch ( IOException e )
333         {
334             fireTransferError( resource, e, TransferEvent.REQUEST_GET );
335 
336             String msg = "GET request of: " + resource.getName() + " from " + repository.getName() + " failed";
337 
338             throw new TransferFailedException( msg, e );
339         }
340         finally
341         {
342             if ( closeInput )
343             {
344                 IOUtil.close( input );
345             }
346 
347             cleanupGetTransfer( resource );
348         }
349     }
350 
351     protected void finishGetTransfer( Resource resource, InputStream input, OutputStream output )
352         throws TransferFailedException
353     {
354     }
355 
356     protected void cleanupGetTransfer( Resource resource )
357     {
358     }
359 
360     protected void putTransfer( Resource resource, File source, OutputStream output, boolean closeOutput )
361         throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
362     {
363         firePutStarted( resource, source );
364 
365         transfer( resource, source, output, closeOutput );
366 
367         firePutCompleted( resource, source );
368     }
369 
370     /**
371      * Write from {@link File} to {@link OutputStream}
372      * 
373      * @since 1.0-beta-1
374      * 
375      * @param resource resource to transfer
376      * @param source file to read from
377      * @param output output stream
378      * @param closeOutput whether the output stream should be closed or not
379      * @throws TransferFailedException
380      * @throws ResourceDoesNotExistException 
381      * @throws AuthorizationException 
382      */
383     protected void transfer( Resource resource, File source, OutputStream output, boolean closeOutput )
384         throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
385     {
386         InputStream input = null;
387 
388         try
389         {
390             input = new FileInputStream( source );
391 
392             putTransfer( resource, input, output, closeOutput );
393         }
394         catch ( FileNotFoundException e )
395         {
396             fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
397 
398             throw new TransferFailedException( "Specified source file does not exist: " + source, e );
399         }
400         finally
401         {
402             IOUtil.close( input );
403         }
404     }
405 
406     protected void putTransfer( Resource resource, InputStream input, OutputStream output, boolean closeOutput )
407         throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
408     {
409         try
410         {
411             transfer( resource, input, output, TransferEvent.REQUEST_PUT );
412             
413             finishPutTransfer( resource, input, output );
414         }
415         catch ( IOException e )
416         {
417             fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
418 
419             String msg = "PUT request to: " + resource.getName() + " in " + repository.getName() + " failed";
420 
421             throw new TransferFailedException( msg, e );
422         }
423         finally
424         {
425             if ( closeOutput )
426             {
427                 IOUtil.close( output );
428             }
429             
430             cleanupPutTransfer( resource );
431         }
432     }
433 
434     protected void cleanupPutTransfer( Resource resource )
435     {
436     }
437 
438     protected void finishPutTransfer( Resource resource, InputStream input, OutputStream output )
439         throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
440     {
441     }
442 
443     /**
444      * Write from {@link InputStream} to {@link OutputStream}.
445      * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, int)} with a maxSize equals to
446      * {@link Integer#MAX_VALUE}
447      * 
448      * @param resource resource to transfer
449      * @param input input stream
450      * @param output output stream
451      * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
452      * @throws IOException
453      */
454     protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType )
455         throws IOException
456     {
457         transfer( resource, input, output, requestType, Integer.MAX_VALUE );
458     }
459 
460     /**
461      * Write from {@link InputStream} to {@link OutputStream}.
462      * Equivalent to {@link #transfer(Resource, InputStream, OutputStream, int, int)} with a maxSize equals to
463      * {@link Integer#MAX_VALUE}
464      * 
465      * @param resource resource to transfer
466      * @param input input stream
467      * @param output output stream
468      * @param requestType one of {@link TransferEvent#REQUEST_GET} or {@link TransferEvent#REQUEST_PUT}
469      * @param maxSize size of the buffer
470      * @throws IOException
471      */
472     protected void transfer( Resource resource, InputStream input, OutputStream output, int requestType, int maxSize )
473         throws IOException
474     {
475         byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
476 
477         TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_PROGRESS, requestType );
478         transferEvent.setTimestamp( System.currentTimeMillis() );
479 
480         int remaining = maxSize;
481         while ( remaining > 0 )
482         {
483             int n = input.read( buffer, 0, Math.min( buffer.length, remaining ) );
484 
485             if ( n == -1 )
486             {
487                 break;
488             }
489 
490             fireTransferProgress( transferEvent, buffer, n );
491 
492             output.write( buffer, 0, n );
493 
494             remaining -= n;
495         }
496         output.flush();
497     }
498 
499     // ----------------------------------------------------------------------
500     //
501     // ----------------------------------------------------------------------
502 
503     protected void fireTransferProgress( TransferEvent transferEvent, byte[] buffer, int n )
504     {
505         transferEventSupport.fireTransferProgress( transferEvent, buffer, n );
506     }
507 
508     protected void fireGetCompleted( Resource resource, File localFile )
509     {
510         long timestamp = System.currentTimeMillis();
511 
512         TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_COMPLETED,
513                                                          TransferEvent.REQUEST_GET );
514 
515         transferEvent.setTimestamp( timestamp );
516 
517         transferEvent.setLocalFile( localFile );
518 
519         transferEventSupport.fireTransferCompleted( transferEvent );
520     }
521 
522     protected void fireGetStarted( Resource resource, File localFile )
523     {
524         long timestamp = System.currentTimeMillis();
525 
526         TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_STARTED,
527                                                          TransferEvent.REQUEST_GET );
528 
529         transferEvent.setTimestamp( timestamp );
530 
531         transferEvent.setLocalFile( localFile );
532 
533         transferEventSupport.fireTransferStarted( transferEvent );
534     }
535 
536     protected void fireGetInitiated( Resource resource, File localFile )
537     {
538         long timestamp = System.currentTimeMillis();
539 
540         TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_INITIATED,
541                                                          TransferEvent.REQUEST_GET );
542 
543         transferEvent.setTimestamp( timestamp );
544 
545         transferEvent.setLocalFile( localFile );
546 
547         transferEventSupport.fireTransferInitiated( transferEvent );
548     }
549 
550     protected void firePutInitiated( Resource resource, File localFile )
551     {
552         long timestamp = System.currentTimeMillis();
553 
554         TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_INITIATED,
555                                                          TransferEvent.REQUEST_PUT );
556 
557         transferEvent.setTimestamp( timestamp );
558 
559         transferEvent.setLocalFile( localFile );
560 
561         transferEventSupport.fireTransferInitiated( transferEvent );
562     }
563 
564     protected void firePutCompleted( Resource resource, File localFile )
565     {
566         long timestamp = System.currentTimeMillis();
567 
568         TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_COMPLETED,
569                                                          TransferEvent.REQUEST_PUT );
570 
571         transferEvent.setTimestamp( timestamp );
572 
573         transferEvent.setLocalFile( localFile );
574 
575         transferEventSupport.fireTransferCompleted( transferEvent );
576     }
577 
578     protected void firePutStarted( Resource resource, File localFile )
579     {
580         long timestamp = System.currentTimeMillis();
581 
582         TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_STARTED,
583                                                          TransferEvent.REQUEST_PUT );
584 
585         transferEvent.setTimestamp( timestamp );
586 
587         transferEvent.setLocalFile( localFile );
588 
589         transferEventSupport.fireTransferStarted( transferEvent );
590     }
591 
592     protected void fireSessionDisconnected()
593     {
594         long timestamp = System.currentTimeMillis();
595 
596         SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_DISCONNECTED );
597 
598         sessionEvent.setTimestamp( timestamp );
599 
600         sessionEventSupport.fireSessionDisconnected( sessionEvent );
601     }
602 
603     protected void fireSessionDisconnecting()
604     {
605         long timestamp = System.currentTimeMillis();
606 
607         SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_DISCONNECTING );
608 
609         sessionEvent.setTimestamp( timestamp );
610 
611         sessionEventSupport.fireSessionDisconnecting( sessionEvent );
612     }
613 
614     protected void fireSessionLoggedIn()
615     {
616         long timestamp = System.currentTimeMillis();
617 
618         SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_LOGGED_IN );
619 
620         sessionEvent.setTimestamp( timestamp );
621 
622         sessionEventSupport.fireSessionLoggedIn( sessionEvent );
623     }
624 
625     protected void fireSessionLoggedOff()
626     {
627         long timestamp = System.currentTimeMillis();
628 
629         SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_LOGGED_OFF );
630 
631         sessionEvent.setTimestamp( timestamp );
632 
633         sessionEventSupport.fireSessionLoggedOff( sessionEvent );
634     }
635 
636     protected void fireSessionOpened()
637     {
638         long timestamp = System.currentTimeMillis();
639 
640         SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_OPENED );
641 
642         sessionEvent.setTimestamp( timestamp );
643 
644         sessionEventSupport.fireSessionOpened( sessionEvent );
645     }
646 
647     protected void fireSessionOpening()
648     {
649         long timestamp = System.currentTimeMillis();
650 
651         SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_OPENING );
652 
653         sessionEvent.setTimestamp( timestamp );
654 
655         sessionEventSupport.fireSessionOpening( sessionEvent );
656     }
657 
658     protected void fireSessionConnectionRefused()
659     {
660         long timestamp = System.currentTimeMillis();
661 
662         SessionEvent sessionEvent = new SessionEvent( this, SessionEvent.SESSION_CONNECTION_REFUSED );
663 
664         sessionEvent.setTimestamp( timestamp );
665 
666         sessionEventSupport.fireSessionConnectionRefused( sessionEvent );
667     }
668 
669     protected void fireSessionError( Exception exception )
670     {
671         long timestamp = System.currentTimeMillis();
672 
673         SessionEvent sessionEvent = new SessionEvent( this, exception );
674 
675         sessionEvent.setTimestamp( timestamp );
676 
677         sessionEventSupport.fireSessionError( sessionEvent );
678 
679     }
680 
681     protected void fireTransferDebug( String message )
682     {
683         transferEventSupport.fireDebug( message );
684     }
685 
686     protected void fireSessionDebug( String message )
687     {
688         sessionEventSupport.fireDebug( message );
689     }
690 
691     public boolean hasTransferListener( TransferListener listener )
692     {
693         return transferEventSupport.hasTransferListener( listener );
694     }
695 
696     public void addTransferListener( TransferListener listener )
697     {
698         transferEventSupport.addTransferListener( listener );
699     }
700 
701     public void removeTransferListener( TransferListener listener )
702     {
703         transferEventSupport.removeTransferListener( listener );
704     }
705 
706     public void addSessionListener( SessionListener listener )
707     {
708         sessionEventSupport.addSessionListener( listener );
709     }
710 
711     public boolean hasSessionListener( SessionListener listener )
712     {
713         return sessionEventSupport.hasSessionListener( listener );
714     }
715 
716     public void removeSessionListener( SessionListener listener )
717     {
718         sessionEventSupport.removeSessionListener( listener );
719     }
720 
721     protected void fireTransferError( Resource resource, Exception e, int requestType )
722     {
723         TransferEvent transferEvent = new TransferEvent( this, resource, e, requestType );
724 
725         transferEventSupport.fireTransferError( transferEvent );
726     }
727 
728 
729     public SessionEventSupport getSessionEventSupport()
730     {
731         return sessionEventSupport;
732     }
733 
734     public void setSessionEventSupport( SessionEventSupport sessionEventSupport )
735     {
736         this.sessionEventSupport = sessionEventSupport;
737     }
738 
739     public TransferEventSupport getTransferEventSupport()
740     {
741         return transferEventSupport;
742     }
743 
744     public void setTransferEventSupport( TransferEventSupport transferEventSupport )
745     {
746         this.transferEventSupport = transferEventSupport;
747     }
748 
749     /**
750      * This method is used if you are not streaming the transfer, to make sure any listeners dependent on state
751      * (eg checksum observers) succeed.
752      */
753     protected void postProcessListeners( Resource resource, File source, int requestType )
754         throws TransferFailedException
755     {
756         byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
757 
758         TransferEvent transferEvent = new TransferEvent( this, resource, TransferEvent.TRANSFER_PROGRESS, requestType );
759         transferEvent.setTimestamp( System.currentTimeMillis() );
760         transferEvent.setLocalFile( source );
761 
762         InputStream input = null;
763         try
764         {
765             input = new FileInputStream( source );
766 
767             while ( true )
768             {
769                 int n = input.read( buffer );
770 
771                 if ( n == -1 )
772                 {
773                     break;
774                 }
775 
776                 fireTransferProgress( transferEvent, buffer, n );
777             }
778         }
779         catch ( IOException e )
780         {
781             fireTransferError( resource, e, requestType );
782             
783             throw new TransferFailedException( "Failed to post-process the source file", e );
784         }
785         finally
786         {
787             IOUtil.close( input );
788         }
789     }
790 
791     public void putDirectory( File sourceDirectory, String destinationDirectory )
792         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
793     {
794         throw new UnsupportedOperationException( "The wagon you are using has not implemented putDirectory()" );
795     }
796 
797     public boolean supportsDirectoryCopy()
798     {
799         return false;
800     }
801 
802     protected static String getPath( String basedir, String dir )
803     {
804         String path;
805         path = basedir;
806         if ( !basedir.endsWith( "/" ) && !dir.startsWith( "/" ) )
807         {
808             path += "/";
809         }
810         path += dir;
811         return path;
812     }
813 
814     public boolean isInteractive()
815     {
816         return interactive;
817     }
818 
819     public void setInteractive( boolean interactive )
820     {
821         this.interactive = interactive;
822     }
823 
824     public List getFileList( String destinationDirectory )
825         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
826     {
827         throw new UnsupportedOperationException( "The wagon you are using has not implemented getFileList()" );
828     }
829 
830     public boolean resourceExists( String resourceName )
831         throws TransferFailedException, AuthorizationException
832     {
833         throw new UnsupportedOperationException( "The wagon you are using has not implemented resourceExists()" );
834     }
835 
836     protected ProxyInfo getProxyInfo( String protocol, String host )
837     {
838         if ( proxyInfoProvider != null )
839         {
840             ProxyInfo proxyInfo = proxyInfoProvider.getProxyInfo( protocol );
841             if ( !ProxyUtils.validateNonProxyHosts( proxyInfo, host ) )
842             {
843                 return proxyInfo;
844             }
845         }
846         return null;
847     }
848 
849     public RepositoryPermissions getPermissionsOverride()
850     {
851         return permissionsOverride;
852     }
853 
854     public void setPermissionsOverride( RepositoryPermissions permissionsOverride )
855     {
856         this.permissionsOverride = permissionsOverride;
857     }
858 }