001package org.apache.maven.wagon.tck.http;
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.ConnectionException;
023import org.apache.maven.wagon.ResourceDoesNotExistException;
024import org.apache.maven.wagon.StreamWagon;
025import org.apache.maven.wagon.TransferFailedException;
026import org.apache.maven.wagon.authentication.AuthenticationException;
027import org.apache.maven.wagon.authentication.AuthenticationInfo;
028import org.apache.maven.wagon.authorization.AuthorizationException;
029import org.apache.maven.wagon.proxy.ProxyInfo;
030import org.apache.maven.wagon.tck.http.fixture.ErrorCodeServlet;
031import org.apache.maven.wagon.tck.http.fixture.LatencyServlet;
032import org.apache.maven.wagon.tck.http.fixture.ProxyConnectionVerifierFilter;
033import org.apache.maven.wagon.tck.http.fixture.RedirectionServlet;
034import org.apache.maven.wagon.tck.http.fixture.ServerFixture;
035import org.apache.maven.wagon.tck.http.fixture.ServletExceptionServlet;
036import org.apache.maven.wagon.tck.http.util.ValueHolder;
037import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
038import org.junit.Ignore;
039import org.junit.Test;
040
041import javax.servlet.Servlet;
042import javax.servlet.http.HttpServletResponse;
043import java.io.File;
044import java.io.IOException;
045
046import static junit.framework.Assert.assertTrue;
047import static junit.framework.Assert.fail;
048import static org.apache.maven.wagon.tck.http.Assertions.assertFileContentsFromResource;
049
050/**
051 * 
052 */
053public class GetWagonTests
054    extends HttpWagonTests
055{
056    private static final int TWO_SECONDS = 2000;
057    private static final int ONE_MINUTE = 60000;
058
059    @Test
060    public void basic()
061        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
062        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
063    {
064        testSuccessfulGet( "base.txt" );
065    }
066
067    @Test
068    @Ignore( "FIX ME!" )
069    public void proxied()
070        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
071        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
072    {
073        getServerFixture().addFilter( "*", new ProxyConnectionVerifierFilter() );
074
075        ProxyInfo info = newProxyInfo();
076        if ( !initTest( null, info ) )
077        {
078            return;
079        }
080
081        File target = newTempFile();
082        getWagon().get( "base.txt", target );
083
084        assertFileContentsFromResource( ServerFixture.SERVER_ROOT_RESOURCE_PATH, "base.txt", target,
085                                        "Downloaded file doesn't match original." );
086    }
087
088    @Test
089    public void highLatencyHighTimeout()
090        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
091        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
092    {
093        getServerFixture().addServlet( "/slow/*", new LatencyServlet( TWO_SECONDS ) );
094        testSuccessfulGet( "slow/large.txt", "large.txt" );
095    }
096
097    @Test
098    public void highLatencyLowTimeout()
099        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
100        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
101    {
102        Servlet servlet = new LatencyServlet( TWO_SECONDS );
103        getServerFixture().addServlet( "/slow/*", servlet );
104        testSuccessfulGet( "slow/large.txt", "large.txt" );
105    }
106
107    @Test
108    public void inifiniteLatencyTimeout()
109        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
110        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
111    {
112        if ( !isSupported() )
113        {
114            return;
115        }
116
117        final ValueHolder<Boolean> holder = new ValueHolder<Boolean>( false );
118
119        Runnable r = new Runnable()
120        {
121            public void run()
122            {
123                Servlet servlet = new LatencyServlet( -1 );
124                addNotificationTarget( servlet );
125
126                getServerFixture().addServlet( "/infinite/*", servlet );
127                try
128                {
129                    if ( !initTest( null, null ) )
130                    {
131                        return;
132                    }
133
134                    if ( getWagon() instanceof StreamWagon )
135                    {
136                        LOGGER.info( "Connection timeout is: " + getWagon().getTimeout() );
137                    }
138
139                    File target = newTempFile();
140                    getWagon().get( "infinite/", target );
141
142                    fail( "Should have failed to transfer due to transaction timeout." );
143                }
144                catch ( ConnectionException e )
145                {
146                    throw new IllegalStateException( e );
147                }
148                catch ( AuthenticationException e )
149                {
150                    throw new IllegalStateException( e );
151                }
152                catch ( TransferFailedException e )
153                {
154                    // expected
155                    holder.setValue( true );
156                }
157                catch ( ResourceDoesNotExistException e )
158                {
159                    throw new IllegalStateException( e );
160                }
161                catch ( AuthorizationException e )
162                {
163                    throw new IllegalStateException( e );
164                }
165                catch ( ComponentConfigurationException e )
166                {
167                    throw new IllegalStateException( e );
168                }
169                catch ( IOException e )
170                {
171                    throw new IllegalStateException( e );
172                }
173            }
174        };
175
176        Thread t = new Thread( r );
177        t.start();
178
179        try
180        {
181            LOGGER.info( "Waiting 60 seconds for wagon timeout." );
182            t.join( ONE_MINUTE );
183        }
184        catch ( InterruptedException e )
185        {
186            e.printStackTrace();
187        }
188
189        LOGGER.info( "Interrupting thread." );
190        t.interrupt();
191
192        assertTrue( "TransferFailedException should have been thrown.", holder.getValue() );
193    }
194
195    @Test
196    public void nonExistentHost()
197        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
198        ResourceDoesNotExistException, AuthorizationException
199    {
200        // we use a invalid localhost URL since some Internet Service Providers lately
201        // use funny 'search-DNS' which don't handle explicitly marked testing DNS properly.
202        // According to RFC-2606 .test, .invalid TLDs etc should work, but in practice it doesn't :(
203        if ( !initTest( "http://localhost:65520", null, null ) )
204        {
205            return;
206        }
207
208        File target = newTempFile();
209        try
210        {
211            getWagon().get( "base.txt", target );
212            fail( "Expected error related to host lookup failure." );
213        }
214        catch ( TransferFailedException e )
215        {
216            // expected
217        }
218    }
219
220    @Test
221    public void oneLevelPermanentMove()
222        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
223        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
224    {
225        getServerFixture().addServlet( "/moved.txt",
226                                       new RedirectionServlet( HttpServletResponse.SC_MOVED_PERMANENTLY,
227                                                               "/base.txt" ) );
228
229        testSuccessfulGet( "moved.txt" );
230    }
231
232    @Test
233    public void oneLevelTemporaryMove()
234        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
235        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
236    {
237        getServerFixture().addServlet( "/moved.txt",
238                                       new RedirectionServlet( HttpServletResponse.SC_MOVED_TEMPORARILY,
239                                                               "/base.txt" ) );
240
241        testSuccessfulGet( "moved.txt" );
242    }
243
244    @Test
245    public void sixLevelPermanentMove()
246        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
247        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
248    {
249        String myPath = "moved.txt";
250        String targetPath = "/base.txt";
251
252        getServerFixture().addServlet( "/" + myPath + "/*",
253                                       new RedirectionServlet( HttpServletResponse.SC_MOVED_PERMANENTLY, myPath,
254                                                               targetPath, 6 ) );
255
256        testSuccessfulGet( myPath );
257    }
258
259    @Test
260    public void sixLevelTemporaryMove()
261        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
262        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
263    {
264        String myPath = "moved.txt";
265        String targetPath = "/base.txt";
266
267        getServerFixture().addServlet( "/" + myPath + "/*",
268                                       new RedirectionServlet( HttpServletResponse.SC_MOVED_TEMPORARILY, myPath,
269                                                               targetPath, 6 ) );
270
271        testSuccessfulGet( myPath );
272    }
273
274    @Test
275    public void infinitePermanentMove()
276        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
277        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
278    {
279        String myPath = "moved.txt";
280        String targetPath = "/base.txt";
281
282        getServerFixture().addServlet(
283                                       "/" + myPath,
284                                       new RedirectionServlet( HttpServletResponse.SC_MOVED_PERMANENTLY, myPath,
285                                                               targetPath, -1 ) );
286
287        try
288        {
289            testSuccessfulGet( myPath );
290            fail( "Expected failure as a result of too many redirects." );
291        }
292        catch ( TransferFailedException e )
293        {
294            // expected
295        }
296    }
297
298    @Test
299    public void infiniteTemporaryMove()
300        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
301        ResourceDoesNotExistException, AuthorizationException
302    {
303        String myPath = "moved.txt";
304        String targetPath = "/base.txt";
305
306        getServerFixture().addServlet(
307                                       "/" + myPath,
308                                       new RedirectionServlet( HttpServletResponse.SC_MOVED_TEMPORARILY, myPath,
309                                                               targetPath, -1 ) );
310
311        try
312        {
313            testSuccessfulGet( myPath );
314            fail( "Expected failure as a result of too many redirects." );
315        }
316        catch ( TransferFailedException e )
317        {
318            // expected
319        }
320    }
321
322    /**
323     * NOTE: This test depends on a {@link WagonTestCaseConfigurator} configuration to limit redirects to 20. In the
324     * case of the Sun HTTP implementation, this is the default limit.
325     */
326    @Test
327    @SuppressWarnings( "checkstyle:methodname" )
328    public void permanentMove_TooManyRedirects_limit20()
329        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
330        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
331    {
332        String myPath = "moved.txt";
333        String targetPath = "/base.txt";
334
335        getServerFixture().addServlet(
336                                       "/" + myPath,
337                                       new RedirectionServlet( HttpServletResponse.SC_MOVED_PERMANENTLY, myPath,
338                                                               targetPath, -1 ) );
339
340        try
341        {
342            testSuccessfulGet( myPath );
343            fail( "Expected failure as a result of too many redirects." );
344        }
345        catch ( TransferFailedException e )
346        {
347            // expected
348        }
349    }
350
351    /**
352     * NOTE: This test depends on a {@link WagonTestCaseConfigurator} configuration to limit redirects to 20. In the
353     * case of the Sun HTTP implementation, this is the default limit.
354     */
355    @Test
356    @SuppressWarnings( "checkstyle:methodname" )
357    public void temporaryMove_TooManyRedirects_limit20()
358        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
359        ResourceDoesNotExistException, AuthorizationException
360    {
361        String myPath = "moved.txt";
362        String targetPath = "/base.txt";
363
364        getServerFixture().addServlet(
365                                       "/" + myPath,
366                                       new RedirectionServlet( HttpServletResponse.SC_MOVED_TEMPORARILY, myPath,
367                                                               targetPath, -1 ) );
368
369        try
370        {
371            testSuccessfulGet( myPath );
372            fail( "Expected failure as a result of too many redirects." );
373        }
374        catch ( TransferFailedException e )
375        {
376            // expected
377        }
378    }
379
380    @Test
381    public void missing()
382        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
383        TransferFailedException, AuthorizationException
384    {
385        if ( !initTest( null, null ) )
386        {
387            return;
388        }
389
390        File target = newTempFile();
391        try
392        {
393            getWagon().get( "404.txt", target );
394            fail( "should have received a 404, meaning the resource doesn't exist." );
395        }
396        catch ( ResourceDoesNotExistException e )
397        {
398            // expected
399        }
400    }
401
402    @Test
403    public void error()
404        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
405        AuthorizationException, ResourceDoesNotExistException
406    {
407        testErrorHandling( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
408    }
409
410    @Test
411    public void proxyTimeout()
412        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
413        AuthorizationException, ResourceDoesNotExistException
414    {
415        testErrorHandling( HttpServletResponse.SC_GATEWAY_TIMEOUT );
416    }
417
418    @Test
419    public void forbidden()
420        throws ConnectionException, ComponentConfigurationException, IOException, ResourceDoesNotExistException,
421        TransferFailedException
422    {
423        AuthenticationInfo info = new AuthenticationInfo();
424        info.setUserName( "user" );
425        info.setPassword( "password" );
426
427        getServerFixture().addUser( info.getUserName(), "password" );
428
429        getServerFixture().addServlet( "/403.txt",
430                                       new ErrorCodeServlet( HttpServletResponse.SC_FORBIDDEN, "Expected 403" ) );
431
432        testAuthFailure( "403.txt", info );
433    }
434
435    @Test
436    public void successfulAuthentication()
437        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
438        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
439    {
440        AuthenticationInfo info = new AuthenticationInfo();
441        info.setUserName( "user" );
442        info.setPassword( "password" );
443
444        getServerFixture().addUser( info.getUserName(), info.getPassword() );
445
446        if ( !initTest( info, null ) )
447        {
448            return;
449        }
450
451        File target = newTempFile();
452        getWagon().get( "protected/base.txt", target );
453
454        assertFileContentsFromResource( ServerFixture.SERVER_ROOT_RESOURCE_PATH, "base.txt", target,
455                                        "Downloaded file doesn't match original." );
456    }
457
458    @Test
459    public void unsuccessfulAuthentication()
460        throws ConnectionException, ComponentConfigurationException, IOException, TransferFailedException,
461        ResourceDoesNotExistException
462    {
463        AuthenticationInfo info = new AuthenticationInfo();
464        info.setUserName( "user" );
465        info.setPassword( "password" );
466
467        getServerFixture().addUser( info.getUserName(), "anotherPassword" );
468
469        testAuthFailure( "protected/base.txt", info );
470    }
471
472    protected void testAuthFailure( final String path, final AuthenticationInfo info )
473        throws ConnectionException, ComponentConfigurationException, IOException, TransferFailedException,
474        ResourceDoesNotExistException
475    {
476        boolean authFailure = false;
477        try
478        {
479            if ( !initTest( info, null ) )
480            {
481                return;
482            }
483        }
484        catch ( AuthenticationException e )
485        {
486            // expected
487            authFailure = true;
488        }
489
490        File target = newTempFile();
491        try
492        {
493            getWagon().get( path, target );
494        }
495        catch ( AuthorizationException e )
496        {
497            // expected
498            authFailure = true;
499        }
500
501        assertTrue( "Authentication/Authorization should have failed.", authFailure );
502    }
503
504    protected void testSuccessfulGet( final String path )
505        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
506        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
507    {
508        testSuccessfulGet( path, "base.txt" );
509    }
510
511    protected void testSuccessfulGet( final String path, final String checkPath )
512        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
513        TransferFailedException, ResourceDoesNotExistException, AuthorizationException
514    {
515        if ( !initTest( null, null ) )
516        {
517            return;
518        }
519
520        if ( getWagon() instanceof StreamWagon )
521        {
522            LOGGER.info( "Connection timeout is: " + getWagon().getTimeout() );
523        }
524
525        File target = newTempFile();
526        getWagon().get( path, target );
527
528        assertFileContentsFromResource( ServerFixture.SERVER_ROOT_RESOURCE_PATH, checkPath, target,
529                                        "Downloaded file doesn't match original." );
530    }
531
532    protected void testErrorHandling( final int code )
533        throws ConnectionException, AuthenticationException, ComponentConfigurationException, IOException,
534        AuthorizationException, ResourceDoesNotExistException
535    {
536        if ( code == HttpServletResponse.SC_INTERNAL_SERVER_ERROR )
537        {
538            getServerFixture().addServlet( "/" + code + ".txt", new ServletExceptionServlet( "Expected " + code ) );
539        }
540        else
541        {
542            getServerFixture().addServlet( "/" + code + ".txt", new ErrorCodeServlet( code, "Expected " + code ) );
543        }
544
545        if ( !initTest( null, null ) )
546        {
547            return;
548        }
549
550        File target = newTempFile();
551        try
552        {
553            getWagon().get( code + ".txt", target );
554            fail( "should have received a " + code + " error code, meaning the resource doesn't exist." );
555        }
556        catch ( TransferFailedException e )
557        {
558            // expected
559        }
560    }
561}