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 junit.framework.TestCase;
023import org.apache.maven.wagon.authentication.AuthenticationException;
024import org.apache.maven.wagon.authentication.AuthenticationInfo;
025import org.apache.maven.wagon.authorization.AuthorizationException;
026import org.apache.maven.wagon.events.SessionEvent;
027import org.apache.maven.wagon.events.SessionListener;
028import org.apache.maven.wagon.events.TransferEvent;
029import org.apache.maven.wagon.events.TransferListener;
030import org.apache.maven.wagon.proxy.ProxyInfo;
031import org.apache.maven.wagon.proxy.ProxyInfoProvider;
032import org.apache.maven.wagon.repository.Repository;
033import org.apache.maven.wagon.repository.RepositoryPermissions;
034import org.apache.maven.wagon.resource.Resource;
035import org.codehaus.plexus.util.FileUtils;
036import org.codehaus.plexus.util.IOUtil;
037import org.easymock.IAnswer;
038
039import static org.easymock.EasyMock.*;
040
041import java.io.ByteArrayOutputStream;
042import java.io.File;
043import java.io.IOException;
044import java.io.InputStream;
045import java.io.OutputStream;
046
047/**
048 * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
049 */
050public class AbstractWagonTest
051    extends TestCase
052{
053    private static class TestWagon
054        extends AbstractWagon
055    {
056        protected void closeConnection()
057            throws ConnectionException
058        {
059        }
060
061        protected void openConnectionInternal()
062            throws ConnectionException, AuthenticationException
063        {
064        }
065
066        public void get( String resourceName, File destination )
067            throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
068        {
069        }
070
071        public boolean getIfNewer( String resourceName, File destination, long timestamp )
072            throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
073        {
074            return false;
075        }
076
077        public void put( File source, String destination )
078            throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
079        {
080        }
081    }
082
083    private String basedir;
084
085    private WagonMock wagon = null;
086
087    private File destination;
088
089    private File source;
090
091    private String artifact;
092
093    private SessionListener sessionListener = null;
094
095    private TransferListener transferListener = null;
096
097    protected void setUp()
098        throws Exception
099    {
100        super.setUp();
101
102        basedir = System.getProperty( "basedir" );
103
104        destination = new File( basedir, "target/folder/subfolder" );
105
106        source = new File( basedir, "pom.xml" );
107
108        wagon = new WagonMock();
109
110        sessionListener = createMock( SessionListener.class );
111
112        wagon.addSessionListener( sessionListener );
113
114        transferListener = createMock( TransferListener.class );
115
116        wagon.addTransferListener( transferListener );
117
118    }
119
120    public void testCalculationOfTransferBufferSize() {
121        // 1 KiB -> Default buffer size (4 KiB)
122        assertEquals( 4096, wagon.getBufferCapacityForTransfer(1024L ) );
123
124        // 1 MiB -> Twice the default buffer size (8 KiB)
125        assertEquals( 4096 * 2, wagon.getBufferCapacityForTransfer(1024L * 1024 ) );
126
127        // 100 MiB -> Maximum buffer size (512 KiB)
128        assertEquals( 4096 * 128, wagon.getBufferCapacityForTransfer(1024L * 1024  * 100 ) );
129
130        // 1 GiB -> Maximum buffer size (512 KiB)
131        assertEquals( 4096 * 128, wagon.getBufferCapacityForTransfer(1024L * 1024  * 1024 ) );
132
133        // 100 GiB -> Maximum buffer size (512 KiB)
134        assertEquals( 4096 * 128, wagon.getBufferCapacityForTransfer(1024L * 1024  * 1024 * 100 ) );
135    }
136
137    public void testSessionListenerRegistration()
138    {
139        assertTrue( wagon.hasSessionListener( sessionListener ) );
140
141        wagon.removeSessionListener( sessionListener );
142
143        assertFalse( wagon.hasSessionListener( sessionListener ) );
144    }
145
146    public void testTransferListenerRegistration()
147    {
148        assertTrue( wagon.hasTransferListener( transferListener ) );
149
150        wagon.removeTransferListener( transferListener );
151
152        assertFalse( wagon.hasTransferListener( transferListener ) );
153    }
154
155    public void testNoProxyConfiguration()
156        throws ConnectionException, AuthenticationException
157    {
158        Repository repository = new Repository();
159        wagon.connect( repository );
160        assertNull( wagon.getProxyInfo() );
161        assertNull( wagon.getProxyInfo( "http", "www.example.com" ) );
162        assertNull( wagon.getProxyInfo( "dav", "www.example.com" ) );
163        assertNull( wagon.getProxyInfo( "scp", "www.example.com" ) );
164        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
165        assertNull( wagon.getProxyInfo( "http", "localhost" ) );
166    }
167
168    public void testNullProxyConfiguration()
169        throws ConnectionException, AuthenticationException
170    {
171        Repository repository = new Repository();
172        wagon.connect( repository, (ProxyInfo) null );
173        assertNull( wagon.getProxyInfo() );
174        assertNull( wagon.getProxyInfo( "http", "www.example.com" ) );
175        assertNull( wagon.getProxyInfo( "dav", "www.example.com" ) );
176        assertNull( wagon.getProxyInfo( "scp", "www.example.com" ) );
177        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
178        assertNull( wagon.getProxyInfo( "http", "localhost" ) );
179
180        wagon.connect( repository );
181        assertNull( wagon.getProxyInfo() );
182        assertNull( wagon.getProxyInfo( "http", "www.example.com" ) );
183        assertNull( wagon.getProxyInfo( "dav", "www.example.com" ) );
184        assertNull( wagon.getProxyInfo( "scp", "www.example.com" ) );
185        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
186        assertNull( wagon.getProxyInfo( "http", "localhost" ) );
187
188        wagon.connect( repository, new AuthenticationInfo() );
189        assertNull( wagon.getProxyInfo() );
190        assertNull( wagon.getProxyInfo( "http", "www.example.com" ) );
191        assertNull( wagon.getProxyInfo( "dav", "www.example.com" ) );
192        assertNull( wagon.getProxyInfo( "scp", "www.example.com" ) );
193        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
194        assertNull( wagon.getProxyInfo( "http", "localhost" ) );
195    }
196
197    public void testLegacyProxyConfiguration()
198        throws ConnectionException, AuthenticationException
199    {
200        ProxyInfo proxyInfo = new ProxyInfo();
201        proxyInfo.setType( "http" );
202
203        Repository repository = new Repository();
204        wagon.connect( repository, proxyInfo );
205        assertEquals( proxyInfo, wagon.getProxyInfo() );
206        assertEquals( proxyInfo, wagon.getProxyInfo( "http", "www.example.com" ) );
207        assertNull( wagon.getProxyInfo( "dav", "www.example.com" ) );
208        assertNull( wagon.getProxyInfo( "scp", "www.example.com" ) );
209        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
210    }
211
212    public void testProxyConfiguration()
213        throws ConnectionException, AuthenticationException
214    {
215        final ProxyInfo httpProxyInfo = new ProxyInfo();
216        httpProxyInfo.setType( "http" );
217
218        final ProxyInfo socksProxyInfo = new ProxyInfo();
219        socksProxyInfo.setType( "http" );
220
221        ProxyInfoProvider proxyInfoProvider = new ProxyInfoProvider()
222        {
223            public ProxyInfo getProxyInfo( String protocol )
224            {
225                if ( "http".equals( protocol ) || "dav".equals( protocol ) )
226                {
227                    return httpProxyInfo;
228                }
229                else if ( "scp".equals( protocol ) )
230                {
231                    return socksProxyInfo;
232                }
233                return null;
234            }
235        };
236
237        Repository repository = new Repository();
238        wagon.connect( repository, proxyInfoProvider );
239        assertNull( wagon.getProxyInfo() );
240        assertEquals( httpProxyInfo, wagon.getProxyInfo( "http", "www.example.com" ) );
241        assertEquals( httpProxyInfo, wagon.getProxyInfo( "dav", "www.example.com" ) );
242        assertEquals( socksProxyInfo, wagon.getProxyInfo( "scp", "www.example.com" ) );
243        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
244    }
245
246    public void testSessionOpenEvents()
247        throws Exception
248    {
249        Repository repository = new Repository();
250
251        sessionListener.sessionOpening( anyObject( SessionEvent.class ) );
252        sessionListener.sessionOpened( anyObject( SessionEvent.class ) );
253        replay( sessionListener );
254
255        wagon.connect( repository );
256
257        verify( sessionListener );
258
259        assertEquals( repository, wagon.getRepository() );
260    }
261
262    public void testSessionConnectionRefusedEventConnectionException()
263        throws Exception
264    {
265        final WagonException exception = new ConnectionException( "" );
266
267        try
268        {
269            runTestSessionConnectionRefusedEvent( exception );
270            fail();
271        }
272        catch ( ConnectionException e )
273        {
274            assertTrue( true );
275        }
276    }
277
278    public void testSessionConnectionRefusedEventAuthenticationException()
279        throws Exception
280    {
281        final WagonException exception = new AuthenticationException( "" );
282
283        try
284        {
285            runTestSessionConnectionRefusedEvent( exception );
286            fail();
287        }
288        catch ( AuthenticationException e )
289        {
290            assertTrue( true );
291        }
292    }
293
294    private void runTestSessionConnectionRefusedEvent( final WagonException exception )
295        throws ConnectionException, AuthenticationException
296    {
297        Repository repository = new Repository();
298
299        sessionListener.sessionOpening( anyObject( SessionEvent.class ) );
300        sessionListener.sessionConnectionRefused( anyObject( SessionEvent.class ) );
301        replay( sessionListener );
302
303        Wagon wagon = new TestWagon()
304        {
305            protected void openConnectionInternal()
306                throws ConnectionException, AuthenticationException
307            {
308                if ( exception instanceof ConnectionException )
309                {
310                    throw (ConnectionException) exception;
311                }
312                if ( exception instanceof AuthenticationException )
313                {
314                    throw (AuthenticationException) exception;
315                }
316            }
317        };
318        wagon.addSessionListener( sessionListener );
319
320        try
321        {
322            wagon.connect( repository );
323            fail();
324        }
325        finally
326        {
327            verify( sessionListener );
328
329            assertEquals( repository, wagon.getRepository() );
330        }
331    }
332
333    public void testSessionCloseEvents()
334        throws Exception
335    {
336        sessionListener.sessionDisconnecting( anyObject( SessionEvent.class ) );
337        sessionListener.sessionDisconnected( anyObject( SessionEvent.class ) );
338        replay( sessionListener );
339
340        wagon.disconnect();
341
342        verify( sessionListener );
343    }
344
345    public void testSessionCloseRefusedEventConnectionException()
346        throws Exception
347    {
348        Repository repository = new Repository();
349
350        sessionListener.sessionDisconnecting( anyObject( SessionEvent.class ) );
351        sessionListener.sessionError( anyObject( SessionEvent.class ) );
352        replay( sessionListener );
353
354        Wagon wagon = new TestWagon()
355        {
356            protected void closeConnection()
357                throws ConnectionException
358            {
359                throw new ConnectionException( "" );
360            }
361        };
362        wagon.addSessionListener( sessionListener );
363
364        try
365        {
366            wagon.disconnect();
367            fail();
368        }
369        catch ( ConnectionException e )
370        {
371            assertTrue( true );
372        }
373        finally
374        {
375            verify( sessionListener );
376        }
377    }
378
379    public void testGetTransferEvents()
380        throws Exception
381    {
382        transferListener.debug( "fetch debug message" );
383        transferListener.transferInitiated( anyObject( TransferEvent.class ) );
384        transferListener.transferStarted( anyObject( TransferEvent.class ) );
385        transferListener.debug( anyString() );
386        expectLastCall().anyTimes();
387        transferListener.transferProgress( anyObject( TransferEvent.class ), anyObject( byte[].class ), anyInt() );
388        expectLastCall().times( 5 );
389        transferListener.transferCompleted( anyObject( TransferEvent.class ) );
390        replay( transferListener );
391
392        wagon.fireTransferDebug( "fetch debug message" );
393
394        Repository repository = new Repository();
395        wagon.connect( repository );
396
397        wagon.get( artifact, destination );
398
399        verify( transferListener );
400    }
401
402    public void testGetError()
403        throws Exception
404    {
405        transferListener.transferInitiated( anyObject( TransferEvent.class ) );
406        transferListener.transferStarted( anyObject( TransferEvent.class ) );
407        transferListener.debug( anyString() );
408        expectLastCall().anyTimes();
409        transferListener.transferError( anyObject( TransferEvent.class ) );
410        replay( transferListener );
411
412        try
413        {
414            Repository repository = new Repository();
415
416            WagonMock wagon = new WagonMock( true );
417
418            wagon.addTransferListener( transferListener );
419
420            wagon.connect( repository );
421
422            wagon.get( artifact, destination );
423
424            fail( "Transfer error was expected during deploy" );
425        }
426        catch ( TransferFailedException expected )
427        {
428            assertTrue( true );
429        }
430
431        verify( transferListener );
432    }
433
434    public void testPutTransferEvents()
435        throws ConnectionException, AuthenticationException, ResourceDoesNotExistException, TransferFailedException,
436        AuthorizationException
437    {
438        transferListener.debug( "deploy debug message" );
439        transferListener.transferInitiated( anyObject( TransferEvent.class ) );
440        transferListener.transferStarted( anyObject( TransferEvent.class ) );
441        transferListener.transferProgress( anyObject( TransferEvent.class ), anyObject( byte[].class ), anyInt() );
442        transferListener.transferCompleted( anyObject( TransferEvent.class ) );
443        replay( transferListener );
444
445        wagon.fireTransferDebug( "deploy debug message" );
446
447        Repository repository = new Repository();
448
449        wagon.connect( repository );
450
451        wagon.put( source, artifact );
452
453        verify( transferListener );
454    }
455
456    public void testStreamShutdown()
457    {
458        IOUtil.close( (InputStream) null );
459
460        IOUtil.close( (OutputStream) null );
461
462        InputStreamMock inputStream = new InputStreamMock();
463
464        assertFalse( inputStream.isClosed() );
465
466        IOUtil.close( inputStream );
467
468        assertTrue( inputStream.isClosed() );
469
470        OutputStreamMock outputStream = new OutputStreamMock();
471
472        assertFalse( outputStream.isClosed() );
473
474        IOUtil.close( outputStream );
475
476        assertTrue( outputStream.isClosed() );
477    }
478
479    public void testRepositoryPermissionsOverride()
480        throws ConnectionException, AuthenticationException
481    {
482        Repository repository = new Repository();
483
484        RepositoryPermissions original = new RepositoryPermissions();
485        original.setFileMode( "664" );
486        repository.setPermissions( original );
487
488        RepositoryPermissions override = new RepositoryPermissions();
489        override.setFileMode( "644" );
490        wagon.setPermissionsOverride( override );
491
492        wagon.connect( repository );
493
494        assertEquals( override, repository.getPermissions() );
495        assertEquals( "644", repository.getPermissions().getFileMode() );
496    }
497
498    public void testRepositoryUserName()
499        throws ConnectionException, AuthenticationException
500    {
501        Repository repository = new Repository( "id", "http://bporter:password@www.example.com/path/to/resource" );
502
503        AuthenticationInfo authenticationInfo = new AuthenticationInfo();
504        authenticationInfo.setUserName( "brett" );
505        authenticationInfo.setPassword( "pass" );
506        wagon.connect( repository, authenticationInfo );
507
508        assertEquals( authenticationInfo, wagon.getAuthenticationInfo() );
509        assertEquals( "brett", authenticationInfo.getUserName() );
510        assertEquals( "pass", authenticationInfo.getPassword() );
511    }
512
513    public void testRepositoryUserNameNotGivenInCredentials()
514        throws ConnectionException, AuthenticationException
515    {
516        Repository repository = new Repository( "id", "http://bporter:password@www.example.com/path/to/resource" );
517
518        AuthenticationInfo authenticationInfo = new AuthenticationInfo();
519        wagon.connect( repository, authenticationInfo );
520
521        assertEquals( authenticationInfo, wagon.getAuthenticationInfo() );
522        assertEquals( "bporter", authenticationInfo.getUserName() );
523        assertEquals( "password", authenticationInfo.getPassword() );
524    }
525
526    public void testConnectNullRepository()
527        throws ConnectionException, AuthenticationException
528    {
529        try
530        {
531            wagon.connect( null );
532            fail();
533        }
534        catch ( NullPointerException e )
535        {
536            assertTrue( true );
537        }
538    }
539
540    public void testPostProcessListeners()
541        throws TransferFailedException, IOException
542    {
543        File tempFile = File.createTempFile( "wagon", "tmp" );
544        tempFile.deleteOnExit();
545        String content = "content";
546        FileUtils.fileWrite( tempFile.getAbsolutePath(), content );
547
548        Resource resource = new Resource( "resource" );
549
550        transferListener.transferInitiated( anyObject( TransferEvent.class ) );
551        transferListener.transferStarted( anyObject( TransferEvent.class ) );
552        TransferEvent event =
553            new TransferEvent( wagon, resource, TransferEvent.TRANSFER_PROGRESS, TransferEvent.REQUEST_PUT );
554        event.setLocalFile( tempFile );
555        transferListener.transferProgress( eq( event ), anyObject( byte[].class ), eq( content.length() ) );
556        ProgressAnswer answer = new ProgressAnswer();
557        expectLastCall().andAnswer( answer );
558        transferListener.transferCompleted( anyObject( TransferEvent.class ) );
559        replay( transferListener );
560
561        wagon.postProcessListeners( resource, tempFile, TransferEvent.REQUEST_PUT );
562
563        assertEquals( content.length(), answer.getSize() );
564        assertEquals( new String( content.getBytes() ), new String( answer.getBytes() ) );
565
566        tempFile.delete();
567    }
568
569    static final class ProgressAnswer implements IAnswer
570    {
571        private ByteArrayOutputStream baos = new ByteArrayOutputStream();
572
573        private int size;
574        
575        public Object answer() throws Throwable
576        {
577            byte[] buffer = (byte[]) getCurrentArguments()[1];
578            int length = (Integer) getCurrentArguments()[2];
579            baos.write( buffer, 0, length );
580            size += length;
581            return null;
582        }
583
584        public int getSize()
585        {
586            return size;
587        }
588
589        public byte[] getBytes()
590        {
591            return baos.toByteArray();
592        }
593    }
594}