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