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