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