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 testSessionListenerRegistration()
121    {
122        assertTrue( wagon.hasSessionListener( sessionListener ) );
123
124        wagon.removeSessionListener( sessionListener );
125
126        assertFalse( wagon.hasSessionListener( sessionListener ) );
127    }
128
129    public void testTransferListenerRegistration()
130    {
131        assertTrue( wagon.hasTransferListener( transferListener ) );
132
133        wagon.removeTransferListener( transferListener );
134
135        assertFalse( wagon.hasTransferListener( transferListener ) );
136    }
137
138    public void testNoProxyConfiguration()
139        throws ConnectionException, AuthenticationException
140    {
141        Repository repository = new Repository();
142        wagon.connect( repository );
143        assertNull( wagon.getProxyInfo() );
144        assertNull( wagon.getProxyInfo( "http", "www.example.com" ) );
145        assertNull( wagon.getProxyInfo( "dav", "www.example.com" ) );
146        assertNull( wagon.getProxyInfo( "scp", "www.example.com" ) );
147        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
148        assertNull( wagon.getProxyInfo( "http", "localhost" ) );
149    }
150
151    public void testNullProxyConfiguration()
152        throws ConnectionException, AuthenticationException
153    {
154        Repository repository = new Repository();
155        wagon.connect( repository, (ProxyInfo) null );
156        assertNull( wagon.getProxyInfo() );
157        assertNull( wagon.getProxyInfo( "http", "www.example.com" ) );
158        assertNull( wagon.getProxyInfo( "dav", "www.example.com" ) );
159        assertNull( wagon.getProxyInfo( "scp", "www.example.com" ) );
160        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
161        assertNull( wagon.getProxyInfo( "http", "localhost" ) );
162
163        wagon.connect( repository );
164        assertNull( wagon.getProxyInfo() );
165        assertNull( wagon.getProxyInfo( "http", "www.example.com" ) );
166        assertNull( wagon.getProxyInfo( "dav", "www.example.com" ) );
167        assertNull( wagon.getProxyInfo( "scp", "www.example.com" ) );
168        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
169        assertNull( wagon.getProxyInfo( "http", "localhost" ) );
170
171        wagon.connect( repository, new AuthenticationInfo() );
172        assertNull( wagon.getProxyInfo() );
173        assertNull( wagon.getProxyInfo( "http", "www.example.com" ) );
174        assertNull( wagon.getProxyInfo( "dav", "www.example.com" ) );
175        assertNull( wagon.getProxyInfo( "scp", "www.example.com" ) );
176        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
177        assertNull( wagon.getProxyInfo( "http", "localhost" ) );
178    }
179
180    public void testLegacyProxyConfiguration()
181        throws ConnectionException, AuthenticationException
182    {
183        ProxyInfo proxyInfo = new ProxyInfo();
184        proxyInfo.setType( "http" );
185
186        Repository repository = new Repository();
187        wagon.connect( repository, proxyInfo );
188        assertEquals( proxyInfo, wagon.getProxyInfo() );
189        assertEquals( proxyInfo, wagon.getProxyInfo( "http", "www.example.com" ) );
190        assertNull( wagon.getProxyInfo( "dav", "www.example.com" ) );
191        assertNull( wagon.getProxyInfo( "scp", "www.example.com" ) );
192        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
193    }
194
195    public void testProxyConfiguration()
196        throws ConnectionException, AuthenticationException
197    {
198        final ProxyInfo httpProxyInfo = new ProxyInfo();
199        httpProxyInfo.setType( "http" );
200
201        final ProxyInfo socksProxyInfo = new ProxyInfo();
202        socksProxyInfo.setType( "http" );
203
204        ProxyInfoProvider proxyInfoProvider = new ProxyInfoProvider()
205        {
206            public ProxyInfo getProxyInfo( String protocol )
207            {
208                if ( "http".equals( protocol ) || "dav".equals( protocol ) )
209                {
210                    return httpProxyInfo;
211                }
212                else if ( "scp".equals( protocol ) )
213                {
214                    return socksProxyInfo;
215                }
216                return null;
217            }
218        };
219
220        Repository repository = new Repository();
221        wagon.connect( repository, proxyInfoProvider );
222        assertNull( wagon.getProxyInfo() );
223        assertEquals( httpProxyInfo, wagon.getProxyInfo( "http", "www.example.com" ) );
224        assertEquals( httpProxyInfo, wagon.getProxyInfo( "dav", "www.example.com" ) );
225        assertEquals( socksProxyInfo, wagon.getProxyInfo( "scp", "www.example.com" ) );
226        assertNull( wagon.getProxyInfo( "ftp", "www.example.com" ) );
227    }
228
229    public void testSessionOpenEvents()
230        throws Exception
231    {
232        Repository repository = new Repository();
233
234        sessionListener.sessionOpening( anyObject( SessionEvent.class ) );
235        sessionListener.sessionOpened( anyObject( SessionEvent.class ) );
236        replay( sessionListener );
237
238        wagon.connect( repository );
239
240        verify( sessionListener );
241
242        assertEquals( repository, wagon.getRepository() );
243    }
244
245    public void testSessionConnectionRefusedEventConnectionException()
246        throws Exception
247    {
248        final WagonException exception = new ConnectionException( "" );
249
250        try
251        {
252            runTestSessionConnectionRefusedEvent( exception );
253            fail();
254        }
255        catch ( ConnectionException e )
256        {
257            assertTrue( true );
258        }
259    }
260
261    public void testSessionConnectionRefusedEventAuthenticationException()
262        throws Exception
263    {
264        final WagonException exception = new AuthenticationException( "" );
265
266        try
267        {
268            runTestSessionConnectionRefusedEvent( exception );
269            fail();
270        }
271        catch ( AuthenticationException e )
272        {
273            assertTrue( true );
274        }
275    }
276
277    private void runTestSessionConnectionRefusedEvent( final WagonException exception )
278        throws ConnectionException, AuthenticationException
279    {
280        Repository repository = new Repository();
281
282        sessionListener.sessionOpening( anyObject( SessionEvent.class ) );
283        sessionListener.sessionConnectionRefused( anyObject( SessionEvent.class ) );
284        replay( sessionListener );
285
286        Wagon wagon = new TestWagon()
287        {
288            protected void openConnectionInternal()
289                throws ConnectionException, AuthenticationException
290            {
291                if ( exception instanceof ConnectionException )
292                {
293                    throw (ConnectionException) exception;
294                }
295                if ( exception instanceof AuthenticationException )
296                {
297                    throw (AuthenticationException) exception;
298                }
299            }
300        };
301        wagon.addSessionListener( sessionListener );
302
303        try
304        {
305            wagon.connect( repository );
306            fail();
307        }
308        finally
309        {
310            verify( sessionListener );
311
312            assertEquals( repository, wagon.getRepository() );
313        }
314    }
315
316    public void testSessionCloseEvents()
317        throws Exception
318    {
319        sessionListener.sessionDisconnecting( anyObject( SessionEvent.class ) );
320        sessionListener.sessionDisconnected( anyObject( SessionEvent.class ) );
321        replay( sessionListener );
322
323        wagon.disconnect();
324
325        verify( sessionListener );
326    }
327
328    public void testSessionCloseRefusedEventConnectionException()
329        throws Exception
330    {
331        Repository repository = new Repository();
332
333        sessionListener.sessionDisconnecting( anyObject( SessionEvent.class ) );
334        sessionListener.sessionError( anyObject( SessionEvent.class ) );
335        replay( sessionListener );
336
337        Wagon wagon = new TestWagon()
338        {
339            protected void closeConnection()
340                throws ConnectionException
341            {
342                throw new ConnectionException( "" );
343            }
344        };
345        wagon.addSessionListener( sessionListener );
346
347        try
348        {
349            wagon.disconnect();
350            fail();
351        }
352        catch ( ConnectionException e )
353        {
354            assertTrue( true );
355        }
356        finally
357        {
358            verify( sessionListener );
359        }
360    }
361
362    public void testGetTransferEvents()
363        throws Exception
364    {
365        transferListener.debug( "fetch debug message" );
366        transferListener.transferInitiated( anyObject( TransferEvent.class ) );
367        transferListener.transferStarted( anyObject( TransferEvent.class ) );
368        transferListener.debug( anyString() );
369        expectLastCall().anyTimes();
370        transferListener.transferProgress( anyObject( TransferEvent.class ), anyObject( byte[].class ), anyInt() );
371        expectLastCall().times( 5 );
372        transferListener.transferCompleted( anyObject( TransferEvent.class ) );
373        replay( transferListener );
374
375        wagon.fireTransferDebug( "fetch debug message" );
376
377        Repository repository = new Repository();
378        wagon.connect( repository );
379
380        wagon.get( artifact, destination );
381
382        verify( transferListener );
383    }
384
385    public void testGetError()
386        throws Exception
387    {
388        transferListener.transferInitiated( anyObject( TransferEvent.class ) );
389        transferListener.transferStarted( anyObject( TransferEvent.class ) );
390        transferListener.debug( anyString() );
391        expectLastCall().anyTimes();
392        transferListener.transferError( anyObject( TransferEvent.class ) );
393        replay( transferListener );
394
395        try
396        {
397            Repository repository = new Repository();
398
399            WagonMock wagon = new WagonMock( true );
400
401            wagon.addTransferListener( transferListener );
402
403            wagon.connect( repository );
404
405            wagon.get( artifact, destination );
406
407            fail( "Transfer error was expected during deploy" );
408        }
409        catch ( TransferFailedException expected )
410        {
411            assertTrue( true );
412        }
413
414        verify( transferListener );
415    }
416
417    public void testPutTransferEvents()
418        throws ConnectionException, AuthenticationException, ResourceDoesNotExistException, TransferFailedException,
419        AuthorizationException
420    {
421        transferListener.debug( "deploy debug message" );
422        transferListener.transferInitiated( anyObject( TransferEvent.class ) );
423        transferListener.transferStarted( anyObject( TransferEvent.class ) );
424        transferListener.transferProgress( anyObject( TransferEvent.class ), anyObject( byte[].class ), anyInt() );
425        transferListener.transferCompleted( anyObject( TransferEvent.class ) );
426        replay( transferListener );
427
428        wagon.fireTransferDebug( "deploy debug message" );
429
430        Repository repository = new Repository();
431
432        wagon.connect( repository );
433
434        wagon.put( source, artifact );
435
436        verify( transferListener );
437    }
438
439    public void testStreamShutdown()
440    {
441        IOUtil.close( (InputStream) null );
442
443        IOUtil.close( (OutputStream) null );
444
445        InputStreamMock inputStream = new InputStreamMock();
446
447        assertFalse( inputStream.isClosed() );
448
449        IOUtil.close( inputStream );
450
451        assertTrue( inputStream.isClosed() );
452
453        OutputStreamMock outputStream = new OutputStreamMock();
454
455        assertFalse( outputStream.isClosed() );
456
457        IOUtil.close( outputStream );
458
459        assertTrue( outputStream.isClosed() );
460    }
461
462    public void testRepositoryPermissionsOverride()
463        throws ConnectionException, AuthenticationException
464    {
465        Repository repository = new Repository();
466
467        RepositoryPermissions original = new RepositoryPermissions();
468        original.setFileMode( "664" );
469        repository.setPermissions( original );
470
471        RepositoryPermissions override = new RepositoryPermissions();
472        override.setFileMode( "644" );
473        wagon.setPermissionsOverride( override );
474
475        wagon.connect( repository );
476
477        assertEquals( override, repository.getPermissions() );
478        assertEquals( "644", repository.getPermissions().getFileMode() );
479    }
480
481    public void testRepositoryUserName()
482        throws ConnectionException, AuthenticationException
483    {
484        Repository repository = new Repository( "id", "http://bporter:password@www.example.com/path/to/resource" );
485
486        AuthenticationInfo authenticationInfo = new AuthenticationInfo();
487        authenticationInfo.setUserName( "brett" );
488        authenticationInfo.setPassword( "pass" );
489        wagon.connect( repository, authenticationInfo );
490
491        assertEquals( authenticationInfo, wagon.getAuthenticationInfo() );
492        assertEquals( "brett", authenticationInfo.getUserName() );
493        assertEquals( "pass", authenticationInfo.getPassword() );
494    }
495
496    public void testRepositoryUserNameNotGivenInCredentials()
497        throws ConnectionException, AuthenticationException
498    {
499        Repository repository = new Repository( "id", "http://bporter:password@www.example.com/path/to/resource" );
500
501        AuthenticationInfo authenticationInfo = new AuthenticationInfo();
502        wagon.connect( repository, authenticationInfo );
503
504        assertEquals( authenticationInfo, wagon.getAuthenticationInfo() );
505        assertEquals( "bporter", authenticationInfo.getUserName() );
506        assertEquals( "password", authenticationInfo.getPassword() );
507    }
508
509    public void testConnectNullRepository()
510        throws ConnectionException, AuthenticationException
511    {
512        try
513        {
514            wagon.connect( null );
515            fail();
516        }
517        catch ( IllegalStateException e )
518        {
519            assertTrue( true );
520        }
521    }
522
523    public void testPostProcessListeners()
524        throws TransferFailedException, IOException
525    {
526        File tempFile = File.createTempFile( "wagon", "tmp" );
527        tempFile.deleteOnExit();
528        String content = "content";
529        FileUtils.fileWrite( tempFile.getAbsolutePath(), content );
530
531        Resource resource = new Resource( "resource" );
532
533        transferListener.transferInitiated( anyObject( TransferEvent.class ) );
534        transferListener.transferStarted( anyObject( TransferEvent.class ) );
535        TransferEvent event =
536            new TransferEvent( wagon, resource, TransferEvent.TRANSFER_PROGRESS, TransferEvent.REQUEST_PUT );
537        event.setLocalFile( tempFile );
538        transferListener.transferProgress( eq( event ), anyObject( byte[].class ), eq( content.length() ) );
539        ProgressAnswer answer = new ProgressAnswer();
540        expectLastCall().andAnswer( answer );
541        transferListener.transferCompleted( anyObject( TransferEvent.class ) );
542        replay( transferListener );
543
544        wagon.postProcessListeners( resource, tempFile, TransferEvent.REQUEST_PUT );
545
546        assertEquals( content.length(), answer.getSize() );
547        assertEquals( new String( content.getBytes() ), new String( answer.getBytes() ) );
548
549        tempFile.delete();
550    }
551
552    static final class ProgressAnswer implements IAnswer
553    {
554        private ByteArrayOutputStream baos = new ByteArrayOutputStream();
555
556        private int size;
557        
558        public Object answer() throws Throwable
559        {
560            byte[] buffer = (byte[]) getCurrentArguments()[1];
561            int length = (Integer) getCurrentArguments()[2];
562            baos.write( buffer, 0, length );
563            size += length;
564            return null;
565        }
566
567        public int getSize()
568        {
569            return size;
570        }
571
572        public byte[] getBytes()
573        {
574            return baos.toByteArray();
575        }
576    }
577}