001package org.apache.maven.wagon.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.FileTestUtils; 023import org.apache.maven.wagon.ResourceDoesNotExistException; 024import org.apache.maven.wagon.StreamingWagon; 025import org.apache.maven.wagon.StreamingWagonTestCase; 026import org.apache.maven.wagon.TransferFailedException; 027import org.apache.maven.wagon.Wagon; 028import org.apache.maven.wagon.WagonException; 029import org.apache.maven.wagon.authentication.AuthenticationInfo; 030import org.apache.maven.wagon.authorization.AuthorizationException; 031import org.apache.maven.wagon.proxy.ProxyInfo; 032import org.apache.maven.wagon.proxy.ProxyInfoProvider; 033import org.apache.maven.wagon.repository.Repository; 034import org.apache.maven.wagon.resource.Resource; 035import org.codehaus.plexus.util.FileUtils; 036import org.codehaus.plexus.util.IOUtil; 037import org.codehaus.plexus.util.StringUtils; 038import org.eclipse.jetty.http.HttpStatus; 039import org.eclipse.jetty.security.ConstraintMapping; 040import org.eclipse.jetty.security.ConstraintSecurityHandler; 041import org.eclipse.jetty.security.HashLoginService; 042import org.eclipse.jetty.security.SecurityHandler; 043import org.eclipse.jetty.security.authentication.BasicAuthenticator; 044import org.eclipse.jetty.server.Connector; 045import org.eclipse.jetty.server.HttpConfiguration; 046import org.eclipse.jetty.server.HttpConnectionFactory; 047import org.eclipse.jetty.server.Request; 048import org.eclipse.jetty.server.Response; 049import org.eclipse.jetty.server.Server; 050import org.eclipse.jetty.server.ServerConnector; 051import org.eclipse.jetty.server.handler.AbstractHandler; 052import org.eclipse.jetty.server.handler.HandlerCollection; 053import org.eclipse.jetty.servlet.DefaultServlet; 054import org.eclipse.jetty.servlet.ServletContextHandler; 055import org.eclipse.jetty.servlet.ServletHolder; 056import org.eclipse.jetty.util.security.Constraint; 057import org.eclipse.jetty.util.security.Password; 058 059import javax.servlet.ServletException; 060import javax.servlet.http.HttpServletRequest; 061import javax.servlet.http.HttpServletResponse; 062import java.io.ByteArrayOutputStream; 063import java.io.File; 064import java.io.FileInputStream; 065import java.io.FileOutputStream; 066import java.io.IOException; 067import java.io.InputStream; 068import java.io.OutputStream; 069import java.lang.reflect.Method; 070import java.net.URLDecoder; 071import java.util.ArrayList; 072import java.util.Collections; 073import java.util.Enumeration; 074import java.util.HashMap; 075import java.util.List; 076import java.util.Map; 077import java.util.Properties; 078import java.util.concurrent.atomic.AtomicBoolean; 079import java.util.zip.DeflaterOutputStream; 080import java.util.zip.GZIPOutputStream; 081 082/** 083 * 084 */ 085public abstract class HttpWagonTestCase 086 extends StreamingWagonTestCase 087{ 088 public static final int SC_TOO_MANY_REQUESTS = 429; 089 090 private Server server; 091 private ServerConnector connector; 092 093 protected int getLocalPort( Server server ) 094 { 095 Connector connector = server.getConnectors()[0]; 096 return ( ( ServerConnector ) connector ).getLocalPort(); 097 } 098 099 protected void setupWagonTestingFixtures() 100 throws Exception 101 { 102 // File round trip testing 103 104 File file = FileTestUtils.createUniqueFile( "local-repository", "test-resource" ); 105 106 file.delete(); 107 108 file.getParentFile().mkdirs(); 109 110 File repositoryDirectory = getRepositoryDirectory(); 111 FileUtils.deleteDirectory( repositoryDirectory ); 112 repositoryDirectory.mkdirs(); 113 114 server = new Server( ); 115 //connector = new ServerConnector( server, new HttpConnectionFactory( new HttpConfiguration() ) ); 116 //server.addConnector( connector ); 117 connector = addConnector( server ); 118 119 PutHandler putHandler = new PutHandler( repositoryDirectory ); 120 121 ServletContextHandler context = createContext( server, repositoryDirectory ); 122 HandlerCollection handlers = new HandlerCollection(); 123 handlers.addHandler( putHandler ); 124 handlers.addHandler( context ); 125 server.setHandler( handlers ); 126 127 server.start(); 128 } 129 130 protected final int getTestRepositoryPort() 131 { 132 if ( server == null ) 133 { 134 return 0; 135 } 136 return connector.getLocalPort(); 137 } 138 139 protected ServletContextHandler createContext( Server server, File repositoryDirectory ) 140 throws IOException 141 { 142 ServletContextHandler root = new ServletContextHandler( ServletContextHandler.SESSIONS ); 143 root.setResourceBase( repositoryDirectory.getAbsolutePath() ); 144 ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); 145 root.addServlet( servletHolder, "/*" ); 146 return root; 147 } 148 149 protected void tearDownWagonTestingFixtures() 150 throws Exception 151 { 152 server.stop(); 153 } 154 155 public void testWagonGetFileList() 156 throws Exception 157 { 158 File dir = getRepositoryDirectory(); 159 FileUtils.deleteDirectory( dir ); 160 161 File f = new File( dir, "file-list" ); 162 f.mkdirs(); 163 164 super.testWagonGetFileList(); 165 } 166 167 public void testHttpHeaders() 168 throws Exception 169 { 170 Properties properties = new Properties(); 171 properties.setProperty( "User-Agent", "Maven-Wagon/1.0" ); 172 173 StreamingWagon wagon = (StreamingWagon) getWagon(); 174 175 setHttpHeaders( wagon, properties ); 176 177 Server server = new Server( ); 178 TestHeaderHandler handler = new TestHeaderHandler(); 179 server.setHandler( handler ); 180 ServerConnector serverConnector = addConnector( server ); 181 server.start(); 182 183 wagon.connect( 184 new Repository( "id", getProtocol() + "://localhost:" + serverConnector.getLocalPort() ) ); 185 186 wagon.getToStream( "resource", new ByteArrayOutputStream() ); 187 188 wagon.disconnect(); 189 190 server.stop(); 191 192 assertEquals( "Maven-Wagon/1.0", handler.headers.get( "User-Agent" ) ); 193 } 194 195 /** 196 * test set of User-Agent as it's done by aether wagon connector with using setHttpHeaders 197 */ 198 public void testHttpHeadersWithCommonMethods() 199 throws Exception 200 { 201 Properties properties = new Properties(); 202 properties.setProperty( "User-Agent", "Maven-Wagon/1.0" ); 203 204 StreamingWagon wagon = (StreamingWagon) getWagon(); 205 206 Method setHttpHeaders = wagon.getClass().getMethod( "setHttpHeaders", Properties.class ); 207 setHttpHeaders.invoke( wagon, properties ); 208 209 Server server = new Server( ); 210 ServerConnector serverConnector = addConnector( server ); 211 TestHeaderHandler handler = new TestHeaderHandler(); 212 server.setHandler( handler ); 213 addConnector( server ); 214 server.start(); 215 216 wagon.connect( 217 new Repository( "id", getProtocol() + "://localhost:" + serverConnector.getLocalPort() ) ); 218 219 wagon.getToStream( "resource", new ByteArrayOutputStream() ); 220 221 wagon.disconnect(); 222 223 server.stop(); 224 225 assertEquals( "Maven-Wagon/1.0", handler.headers.get( "User-Agent" ) ); 226 } 227 228 public void testUserAgentHeaderIsPresentByDefault() 229 throws Exception 230 { 231 StreamingWagon wagon = (StreamingWagon) getWagon(); 232 Server server = new Server( ); 233 TestHeaderHandler handler = new TestHeaderHandler(); 234 server.setHandler( handler ); 235 addConnector( server ); 236 server.start(); 237 wagon.connect( new Repository( "id", getProtocol() + "://localhost:" + getLocalPort( server ) ) ); 238 wagon.getToStream( "resource", new ByteArrayOutputStream() ); 239 wagon.disconnect(); 240 server.stop(); 241 242 assertNotNull( "default User-Agent header of wagon provider should be present", 243 handler.headers.get( "User-Agent" ) ); 244 } 245 246 public void testUserAgentHeaderIsPresentOnlyOnceIfSetMultipleTimes() 247 throws Exception 248 { 249 StreamingWagon wagon = (StreamingWagon) getWagon(); 250 251 // 1. set User-Agent header via HttpConfiguration 252 Properties headers1 = new Properties(); 253 headers1.setProperty( "User-Agent", "test-user-agent" ); 254 setHttpHeaders( wagon, headers1 ); 255 256 // 2. redundantly set User-Agent header via setHttpHeaders() 257 Properties headers2 = new Properties(); 258 headers2.setProperty( "User-Agent", "test-user-agent" ); 259 Method setHttpHeaders = wagon.getClass().getMethod( "setHttpHeaders", Properties.class ); 260 setHttpHeaders.invoke( wagon, headers2 ); 261 262 Server server = new Server( ); 263 TestHeaderHandler handler = new TestHeaderHandler(); 264 server.setHandler( handler ); 265 addConnector( server ); 266 server.start(); 267 wagon.connect( new Repository( "id", getProtocol() + "://localhost:" + getLocalPort( server ) ) ); 268 wagon.getToStream( "resource", new ByteArrayOutputStream() ); 269 wagon.disconnect(); 270 server.stop(); 271 272 assertEquals( "test-user-agent", handler.headers.get( "User-Agent" ) ); 273 274 } 275 276 protected abstract void setHttpHeaders( StreamingWagon wagon, Properties properties ); 277 278 protected ServerConnector addConnector( Server server ) 279 { 280 ServerConnector serverConnector = 281 new ServerConnector( server, new HttpConnectionFactory( new HttpConfiguration() ) ); 282 server.addConnector( serverConnector ); 283 return serverConnector; 284 } 285 286 protected String getRepositoryUrl( Server server ) 287 { 288 int localPort = getLocalPort( server ); 289 return getProtocol() + "://localhost:" + localPort; 290 } 291 292 public void testGetForbidden() 293 throws Exception 294 { 295 try 296 { 297 runTestGet( HttpServletResponse.SC_FORBIDDEN ); 298 fail(); 299 } 300 catch ( AuthorizationException e ) 301 { 302 assertTrue( true ); 303 } 304 } 305 306 public void testGet404() 307 throws Exception 308 { 309 try 310 { 311 runTestGet( HttpServletResponse.SC_NOT_FOUND ); 312 fail(); 313 } 314 catch ( ResourceDoesNotExistException e ) 315 { 316 assertTrue( true ); 317 } 318 } 319 320 public void testList429() 321 throws Exception 322 { 323 StreamingWagon wagon = (StreamingWagon) getWagon(); 324 try 325 { 326 327 Server server = new Server( ); 328 final AtomicBoolean called = new AtomicBoolean(); 329 330 AbstractHandler handler = new AbstractHandler() 331 { 332 public void handle( String target, Request baseRequest, HttpServletRequest request, 333 HttpServletResponse response ) throws IOException, ServletException 334 { 335 if ( called.get() ) 336 { 337 response.setStatus( HttpServletResponse.SC_OK ); 338 baseRequest.setHandled( true ); 339 } 340 else 341 { 342 called.set( true ); 343 response.setStatus( SC_TOO_MANY_REQUESTS ); 344 baseRequest.setHandled( true ); 345 346 } 347 } 348 }; 349 350 server.setHandler( handler ); 351 ServerConnector serverConnector = addConnector( server ); 352 server.start(); 353 354 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) ); 355 356 try 357 { 358 wagon.getFileList( "resource" ); 359 } 360 finally 361 { 362 wagon.disconnect(); 363 364 server.stop(); 365 } 366 367 } 368 catch ( ResourceDoesNotExistException e ) 369 { 370 assertTrue( true ); 371 } 372 catch ( TransferFailedException e ) 373 { 374 if ( wagon.getClass().getName().contains( "Lightweight" ) ) 375 { 376 //we don't care about lightweight 377 assertTrue( true ); 378 } 379 else 380 { 381 fail(); 382 } 383 384 } 385 } 386 387 public void testGet500() 388 throws Exception 389 { 390 try 391 { 392 runTestGet( HttpServletResponse.SC_INTERNAL_SERVER_ERROR ); 393 fail(); 394 } 395 catch ( TransferFailedException e ) 396 { 397 assertTrue( true ); 398 } 399 } 400 401 private void runTestGet( int status ) 402 throws Exception 403 { 404 StreamingWagon wagon = (StreamingWagon) getWagon(); 405 406 Server server = createStatusServer( status ); 407 server.start(); 408 409 String baseUrl = getRepositoryUrl( server ); 410 String resourceName = "resource"; 411 String serverReasonPhrase = HttpStatus.getCode( status ).getMessage(); 412 413 wagon.connect( new Repository( "id", baseUrl ) ); 414 415 try 416 { 417 wagon.getToStream( "resource", new ByteArrayOutputStream() ); 418 fail(); 419 } 420 catch ( Exception e ) 421 { 422 verifyWagonExceptionMessage( e, status, baseUrl + "/" + resourceName, serverReasonPhrase ); 423 throw e; 424 } 425 finally 426 { 427 wagon.disconnect(); 428 429 server.stop(); 430 } 431 } 432 433 public void testResourceExistsForbidden() 434 throws Exception 435 { 436 try 437 { 438 runTestResourceExists( HttpServletResponse.SC_FORBIDDEN ); 439 fail(); 440 } 441 catch ( AuthorizationException e ) 442 { 443 assertTrue( true ); 444 } 445 } 446 447 public void testResourceExists404() 448 throws Exception 449 { 450 try 451 { 452 assertFalse( runTestResourceExists( HttpServletResponse.SC_NOT_FOUND ) ); 453 } 454 catch ( ResourceDoesNotExistException e ) 455 { 456 assertTrue( true ); 457 } 458 } 459 460 public void testResourceExists500() 461 throws Exception 462 { 463 try 464 { 465 runTestResourceExists( HttpServletResponse.SC_INTERNAL_SERVER_ERROR ); 466 fail(); 467 } 468 catch ( TransferFailedException e ) 469 { 470 assertTrue( true ); 471 } 472 } 473 474 public void testResourceExists429() 475 throws Exception 476 { 477 try 478 { 479 480 final AtomicBoolean called = new AtomicBoolean(); 481 482 AbstractHandler handler = new AbstractHandler() 483 { 484 public void handle( String target, Request baseRequest, HttpServletRequest request, 485 HttpServletResponse response ) throws IOException, ServletException 486 { 487 if ( called.get() ) 488 { 489 response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR ); 490 baseRequest.setHandled( true ); 491 } 492 else 493 { 494 called.set( true ); 495 response.setStatus( SC_TOO_MANY_REQUESTS ); 496 baseRequest.setHandled( true ); 497 } 498 } 499 }; 500 501 StreamingWagon wagon = (StreamingWagon) getWagon(); 502 Server server = new Server( ); 503 server.setHandler( handler ); 504 addConnector( server ); 505 server.start(); 506 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) ); 507 508 try 509 { 510 wagon.resourceExists( "resource" ); 511 } 512 finally 513 { 514 wagon.disconnect(); 515 516 server.stop(); 517 } 518 519 fail(); 520 } 521 catch ( TransferFailedException e ) 522 { 523 assertTrue( true ); 524 } 525 } 526 527 528 private boolean runTestResourceExists( int status ) 529 throws Exception 530 { 531 StreamingWagon wagon = (StreamingWagon) getWagon(); 532 533 Server server = createStatusServer( status ); 534 server.start(); 535 536 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) ); 537 538 try 539 { 540 return wagon.resourceExists( "resource" ); 541 } 542 finally 543 { 544 wagon.disconnect(); 545 546 server.stop(); 547 } 548 } 549 550 protected long getExpectedLastModifiedOnGet( Repository repository, Resource resource ) 551 { 552 File file = new File( getRepositoryDirectory(), resource.getName() ); 553 return ( file.lastModified() / 1000 ) * 1000; 554 } 555 556 protected File getRepositoryDirectory() 557 { 558 return getTestFile( "target/test-output/http-repository" ); 559 } 560 561 public void testGzipGet() 562 throws Exception 563 { 564 Server server = new Server( ); 565 566 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString(); 567 ServletContextHandler root = new ServletContextHandler( ServletContextHandler.SESSIONS ); 568 root.setResourceBase( localRepositoryPath ); 569 ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); 570 servletHolder.setInitParameter( "gzip", "true" ); 571 root.addServlet( servletHolder, "/*" ); 572 addConnector( server ); 573 server.setHandler( root ); 574 server.start(); 575 576 try 577 { 578 Wagon wagon = getWagon(); 579 580 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) ); 581 582 File sourceFile = new File( localRepositoryPath + "/gzip" ); 583 584 sourceFile.deleteOnExit(); 585 586 String resName = "gzip-res.txt"; 587 String sourceContent = writeTestFile( sourceFile, resName, "gzip" ); 588 589 wagon.connect( testRepository ); 590 591 File destFile = FileTestUtils.createUniqueFile( getName(), getName() ); 592 593 destFile.deleteOnExit(); 594 595 wagon.get( "gzip/" + resName, destFile ); 596 597 wagon.disconnect(); 598 599 String destContent = FileUtils.fileRead( destFile ); 600 601 assertEquals( sourceContent, destContent ); 602 } 603 finally 604 { 605 server.stop(); 606 } 607 } 608 609 /* This test cannot be enabled because we cannot tell GzipFilter to compress with deflate only 610 public void testDeflateGet() 611 throws Exception 612 { 613 Server server = new Server( ); 614 615 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString(); 616 ServletContextHandler root = new ServletContextHandler( ServletContextHandler.SESSIONS ); 617 root.setResourceBase( localRepositoryPath ); 618 ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); 619 root.addServlet( servletHolder, "/*" ); 620 FilterHolder filterHolder = new FilterHolder( new GzipFilter() ); 621 root.addFilter( filterHolder, "/deflate/*", EnumSet.of( DispatcherType.REQUEST ) ); 622 addConnector( server ); 623 server.setHandler( root ); 624 server.start(); 625 626 try 627 { 628 Wagon wagon = getWagon(); 629 630 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) ); 631 632 File sourceFile = new File( localRepositoryPath + "/deflate" ); 633 634 sourceFile.deleteOnExit(); 635 636 String resName = "deflate-res.txt"; 637 String sourceContent = writeTestFile( sourceFile, resName, null ); 638 639 wagon.connect( testRepository ); 640 641 File destFile = FileTestUtils.createUniqueFile( getName(), getName() ); 642 643 destFile.deleteOnExit(); 644 645 wagon.get( "deflate/" + resName, destFile ); 646 647 wagon.disconnect(); 648 649 String destContent = FileUtils.fileRead( destFile ); 650 651 assertEquals( sourceContent, destContent ); 652 } 653 finally 654 { 655 server.stop(); 656 } 657 }*/ 658 659 public void testProxiedRequest() 660 throws Exception 661 { 662 ProxyInfo proxyInfo = createProxyInfo(); 663 TestHeaderHandler handler = new TestHeaderHandler(); 664 665 runTestProxiedRequest( proxyInfo, handler ); 666 } 667 668 public void testProxiedRequestWithAuthentication() 669 throws Exception 670 { 671 ProxyInfo proxyInfo = createProxyInfo(); 672 proxyInfo.setUserName( "user" ); 673 proxyInfo.setPassword( "secret" ); 674 AuthorizingProxyHandler handler = new AuthorizingProxyHandler(); 675 676 runTestProxiedRequest( proxyInfo, handler ); 677 678 assertTrue( handler.headers.containsKey( "Proxy-Authorization" ) ); 679 680 if ( supportProxyPreemptiveAuthentication() ) 681 { 682 assertEquals( HttpServletResponse.SC_OK, handler.handlerRequestResponses.get( 0 ).responseCode ); 683 } 684 else 685 { 686 assertEquals( HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED, 687 handler.handlerRequestResponses.get( 0 ).responseCode ); 688 assertEquals( HttpServletResponse.SC_OK, handler.handlerRequestResponses.get( 1 ).responseCode ); 689 } 690 691 } 692 693 public void testProxiedRequestWithAuthenticationWithProvider() 694 throws Exception 695 { 696 final ProxyInfo proxyInfo = createProxyInfo(); 697 proxyInfo.setUserName( "user" ); 698 proxyInfo.setPassword( "secret" ); 699 AuthorizingProxyHandler handler = new AuthorizingProxyHandler(); 700 701 ProxyInfoProvider proxyInfoProvider = new ProxyInfoProvider() 702 { 703 public ProxyInfo getProxyInfo( String protocol ) 704 { 705 return proxyInfo; 706 } 707 }; 708 runTestProxiedRequestWithProvider( proxyInfoProvider, handler ); 709 710 assertTrue( handler.headers.containsKey( "Proxy-Authorization" ) ); 711 712 if ( supportProxyPreemptiveAuthentication() ) 713 { 714 assertEquals( HttpServletResponse.SC_OK, handler.handlerRequestResponses.get( 0 ).responseCode ); 715 } 716 else 717 { 718 assertEquals( HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED, 719 handler.handlerRequestResponses.get( 0 ).responseCode ); 720 assertEquals( HttpServletResponse.SC_OK, handler.handlerRequestResponses.get( 1 ).responseCode ); 721 } 722 723 } 724 725 public void testRedirectGetToStream() 726 throws Exception 727 { 728 StreamingWagon wagon = (StreamingWagon) getWagon(); 729 730 Server realServer = new Server( ); 731 TestHeaderHandler handler = new TestHeaderHandler(); 732 733 realServer.setHandler( handler ); 734 addConnector( realServer ); 735 realServer.start(); 736 737 Server redirectServer = new Server( ); 738 739 addConnector( redirectServer ); 740 741 String protocol = getProtocol(); 742 743 // protocol is wagon protocol but in fact dav is http(s) 744 if ( protocol.equals( "dav" ) ) 745 { 746 protocol = "http"; 747 } 748 749 if ( protocol.equals( "davs" ) ) 750 { 751 protocol = "https"; 752 } 753 754 String redirectUrl = protocol + "://localhost:" + getLocalPort( realServer ); 755 756 RedirectHandler redirectHandler = 757 new RedirectHandler( "See Other", HttpServletResponse.SC_SEE_OTHER, redirectUrl, null ); 758 759 redirectServer.setHandler( redirectHandler ); 760 761 redirectServer.start(); 762 763 wagon.connect( new Repository( "id", getRepositoryUrl( redirectServer ) ) ); 764 765 File tmpResult = File.createTempFile( "foo", "get" ); 766 767 try ( FileOutputStream fileOutputStream = new FileOutputStream( tmpResult ) ) 768 { 769 wagon.getToStream( "resource", fileOutputStream ); 770 fileOutputStream.flush(); 771 fileOutputStream.close(); 772 String found = FileUtils.fileRead( tmpResult ); 773 assertEquals( "found:'" + found + "'", "Hello, World!", found ); 774 775 checkHandlerResult( redirectHandler.handlerRequestResponses, HttpServletResponse.SC_SEE_OTHER ); 776 checkHandlerResult( handler.handlerRequestResponses, HttpServletResponse.SC_OK ); 777 } 778 finally 779 { 780 wagon.disconnect(); 781 782 redirectServer.stop(); 783 realServer.stop(); 784 785 tmpResult.delete(); 786 } 787 } 788 789 public void testRedirectGet() 790 throws Exception 791 { 792 StreamingWagon wagon = (StreamingWagon) getWagon(); 793 794 Server realServer = new Server( ); 795 TestHeaderHandler handler = new TestHeaderHandler(); 796 797 realServer.setHandler( handler ); 798 addConnector( realServer ); 799 realServer.start(); 800 801 Server redirectServer = new Server( ); 802 803 addConnector( redirectServer ); 804 805 String protocol = getProtocol(); 806 807 // protocol is wagon protocol but in fact dav is http(s) 808 if ( protocol.equals( "dav" ) ) 809 { 810 protocol = "http"; 811 } 812 813 if ( protocol.equals( "davs" ) ) 814 { 815 protocol = "https"; 816 } 817 818 String redirectUrl = protocol + "://localhost:" + getLocalPort( realServer ); 819 820 RedirectHandler redirectHandler = 821 new RedirectHandler( "See Other", HttpServletResponse.SC_SEE_OTHER, redirectUrl, null ); 822 823 redirectServer.setHandler( redirectHandler ); 824 825 redirectServer.start(); 826 827 wagon.connect( new Repository( "id", getRepositoryUrl( redirectServer ) ) ); 828 829 File tmpResult = File.createTempFile( "foo", "get" ); 830 831 try 832 { 833 wagon.get( "resource", tmpResult ); 834 String found = FileUtils.fileRead( tmpResult ); 835 assertEquals( "found:'" + found + "'", "Hello, World!", found ); 836 837 checkHandlerResult( redirectHandler.handlerRequestResponses, HttpServletResponse.SC_SEE_OTHER ); 838 checkHandlerResult( handler.handlerRequestResponses, HttpServletResponse.SC_OK ); 839 } 840 finally 841 { 842 wagon.disconnect(); 843 844 redirectServer.stop(); 845 realServer.stop(); 846 847 tmpResult.delete(); 848 } 849 } 850 851 852 public void testRedirectPutFromStreamWithFullUrl() 853 throws Exception 854 { 855 Server realServer = new Server( ); 856 857 addConnector( realServer ); 858 859 File repositoryDirectory = getRepositoryDirectory(); 860 FileUtils.deleteDirectory( repositoryDirectory ); 861 repositoryDirectory.mkdirs(); 862 863 PutHandler putHandler = new PutHandler( repositoryDirectory ); 864 865 realServer.setHandler( putHandler ); 866 867 realServer.start(); 868 869 Server redirectServer = new Server( ); 870 871 addConnector( redirectServer ); 872 873 String protocol = getProtocol(); 874 875 // protocol is wagon protocol but in fact dav is http(s) 876 if ( protocol.equals( "dav" ) ) 877 { 878 protocol = "http"; 879 } 880 881 if ( protocol.equals( "davs" ) ) 882 { 883 protocol = "https"; 884 } 885 886 String redirectUrl = protocol + "://localhost:" + getLocalPort( realServer ); 887 888 RedirectHandler redirectHandler = 889 new RedirectHandler( "See Other", HttpServletResponse.SC_SEE_OTHER, redirectUrl, repositoryDirectory ); 890 891 redirectServer.setHandler( redirectHandler ); 892 893 redirectServer.start(); 894 895 try 896 { 897 StreamingWagon wagon = (StreamingWagon) getWagon(); 898 Repository repository = new Repository( "foo", getRepositoryUrl( redirectServer ) ); 899 wagon.connect( repository ); 900 901 File sourceFile = new File( repositoryDirectory, "test-secured-put-resource" ); 902 sourceFile.delete(); 903 assertFalse( sourceFile.exists() ); 904 905 File tempFile = File.createTempFile( "wagon", "tmp" ); 906 tempFile.deleteOnExit(); 907 String content = "put top secret"; 908 FileUtils.fileWrite( tempFile.getAbsolutePath(), content ); 909 910 try ( FileInputStream fileInputStream = new FileInputStream( tempFile ) ) 911 { 912 wagon.putFromStream( fileInputStream, "test-secured-put-resource", content.length(), -1 ); 913 assertEquals( content, FileUtils.fileRead( sourceFile.getAbsolutePath() ) ); 914 915 checkRequestResponseForRedirectPutWithFullUrl( redirectHandler, putHandler ); 916 } 917 finally 918 { 919 wagon.disconnect(); 920 tempFile.delete(); 921 } 922 923 } 924 finally 925 { 926 realServer.stop(); 927 redirectServer.stop(); 928 } 929 } 930 931 protected void checkRequestResponseForRedirectPutWithFullUrl( RedirectHandler redirectHandler, 932 PutHandler putHandler ) 933 { 934 checkHandlerResult( redirectHandler.handlerRequestResponses, HttpServletResponse.SC_SEE_OTHER ); 935 checkHandlerResult( putHandler.handlerRequestResponses, HttpServletResponse.SC_CREATED ); 936 } 937 938 public void testRedirectPutFromStreamRelativeUrl() 939 throws Exception 940 { 941 Server realServer = new Server( ); 942 addConnector( realServer ); 943 File repositoryDirectory = getRepositoryDirectory(); 944 FileUtils.deleteDirectory( repositoryDirectory ); 945 repositoryDirectory.mkdirs(); 946 947 PutHandler putHandler = new PutHandler( repositoryDirectory ); 948 949 realServer.setHandler( putHandler ); 950 951 realServer.start(); 952 953 Server redirectServer = new Server( ); 954 955 addConnector( redirectServer ); 956 957 RedirectHandler redirectHandler = 958 new RedirectHandler( "See Other", HttpServletResponse.SC_SEE_OTHER, "/redirectRequest/foo", 959 repositoryDirectory ); 960 961 redirectServer.setHandler( redirectHandler ); 962 963 redirectServer.start(); 964 965 try 966 { 967 StreamingWagon wagon = (StreamingWagon) getWagon(); 968 Repository repository = new Repository( "foo", getRepositoryUrl( redirectServer ) ); 969 wagon.connect( repository ); 970 971 File sourceFile = new File( repositoryDirectory, "/redirectRequest/foo/test-secured-put-resource" ); 972 sourceFile.delete(); 973 assertFalse( sourceFile.exists() ); 974 975 File tempFile = File.createTempFile( "wagon", "tmp" ); 976 tempFile.deleteOnExit(); 977 String content = "put top secret"; 978 FileUtils.fileWrite( tempFile.getAbsolutePath(), content ); 979 980 try ( FileInputStream fileInputStream = new FileInputStream( tempFile ) ) 981 { 982 wagon.putFromStream( fileInputStream, "test-secured-put-resource", content.length(), -1 ); 983 assertEquals( content, FileUtils.fileRead( sourceFile.getAbsolutePath() ) ); 984 985 checkRequestResponseForRedirectPutWithRelativeUrl( redirectHandler, putHandler ); 986 } 987 finally 988 { 989 wagon.disconnect(); 990 tempFile.delete(); 991 } 992 993 } 994 finally 995 { 996 realServer.stop(); 997 redirectServer.stop(); 998 } 999 } 1000 1001 protected void checkRequestResponseForRedirectPutWithRelativeUrl( RedirectHandler redirectHandler, 1002 PutHandler putHandler ) 1003 { 1004 checkHandlerResult( redirectHandler.handlerRequestResponses, HttpServletResponse.SC_SEE_OTHER, 1005 HttpServletResponse.SC_CREATED ); 1006 checkHandlerResult( putHandler.handlerRequestResponses ); 1007 } 1008 1009 protected void checkHandlerResult( List<HandlerRequestResponse> handlerRequestResponses, 1010 int... expectedResponseCodes ) 1011 { 1012 boolean success = true; 1013 if ( handlerRequestResponses.size() == expectedResponseCodes.length ) 1014 { 1015 for ( int i = 0; i < expectedResponseCodes.length; i++ ) 1016 { 1017 success &= ( expectedResponseCodes[i] == handlerRequestResponses.get( i ).responseCode ); 1018 } 1019 } 1020 1021 if ( !success ) 1022 { 1023 fail( "expected " + expectedResponseCodes + ", got " + handlerRequestResponses ); 1024 } 1025 } 1026 1027 public void testRedirectPutFileWithFullUrl() 1028 throws Exception 1029 { 1030 Server realServer = new Server( ); 1031 1032 addConnector( realServer ); 1033 1034 File repositoryDirectory = getRepositoryDirectory(); 1035 FileUtils.deleteDirectory( repositoryDirectory ); 1036 repositoryDirectory.mkdirs(); 1037 1038 PutHandler putHandler = new PutHandler( repositoryDirectory ); 1039 1040 realServer.setHandler( putHandler ); 1041 1042 realServer.start(); 1043 1044 Server redirectServer = new Server( ); 1045 1046 addConnector( redirectServer ); 1047 1048 String protocol = getProtocol(); 1049 1050 // protocol is wagon protocol but in fact dav is http(s) 1051 if ( protocol.equals( "dav" ) ) 1052 { 1053 protocol = "http"; 1054 } 1055 1056 if ( protocol.equals( "davs" ) ) 1057 { 1058 protocol = "https"; 1059 } 1060 1061 String redirectUrl = protocol + "://localhost:" + getLocalPort( realServer ); 1062 1063 RedirectHandler redirectHandler = 1064 new RedirectHandler( "See Other", HttpServletResponse.SC_SEE_OTHER, redirectUrl, repositoryDirectory ); 1065 1066 redirectServer.setHandler( redirectHandler ); 1067 1068 redirectServer.start(); 1069 1070 try 1071 { 1072 StreamingWagon wagon = (StreamingWagon) getWagon(); 1073 Repository repository = new Repository( "foo", getRepositoryUrl( redirectServer ) ); 1074 wagon.connect( repository ); 1075 1076 File sourceFile = new File( repositoryDirectory, "test-secured-put-resource" ); 1077 sourceFile.delete(); 1078 assertFalse( sourceFile.exists() ); 1079 1080 File tempFile = File.createTempFile( "wagon", "tmp" ); 1081 tempFile.deleteOnExit(); 1082 String content = "put top secret"; 1083 FileUtils.fileWrite( tempFile.getAbsolutePath(), content ); 1084 1085 try 1086 { 1087 wagon.put( tempFile, "test-secured-put-resource" ); 1088 assertEquals( content, FileUtils.fileRead( sourceFile.getAbsolutePath() ) ); 1089 1090 checkRequestResponseForRedirectPutWithFullUrl( redirectHandler, putHandler ); 1091 } 1092 finally 1093 { 1094 wagon.disconnect(); 1095 tempFile.delete(); 1096 } 1097 1098 } 1099 finally 1100 { 1101 realServer.stop(); 1102 redirectServer.stop(); 1103 } 1104 } 1105 1106 1107 public void testRedirectPutFileRelativeUrl() 1108 throws Exception 1109 { 1110 Server realServer = new Server( ); 1111 addConnector( realServer ); 1112 File repositoryDirectory = getRepositoryDirectory(); 1113 FileUtils.deleteDirectory( repositoryDirectory ); 1114 repositoryDirectory.mkdirs(); 1115 1116 PutHandler putHandler = new PutHandler( repositoryDirectory ); 1117 1118 realServer.setHandler( putHandler ); 1119 1120 realServer.start(); 1121 1122 Server redirectServer = new Server( ); 1123 1124 addConnector( redirectServer ); 1125 1126 RedirectHandler redirectHandler = 1127 new RedirectHandler( "See Other", HttpServletResponse.SC_SEE_OTHER, "/redirectRequest/foo", 1128 repositoryDirectory ); 1129 1130 redirectServer.setHandler( redirectHandler ); 1131 1132 redirectServer.start(); 1133 1134 try 1135 { 1136 StreamingWagon wagon = (StreamingWagon) getWagon(); 1137 Repository repository = new Repository( "foo", getRepositoryUrl( redirectServer ) ); 1138 wagon.connect( repository ); 1139 1140 File sourceFile = new File( repositoryDirectory, "/redirectRequest/foo/test-secured-put-resource" ); 1141 sourceFile.delete(); 1142 assertFalse( sourceFile.exists() ); 1143 1144 File tempFile = File.createTempFile( "wagon", "tmp" ); 1145 tempFile.deleteOnExit(); 1146 String content = "put top secret"; 1147 FileUtils.fileWrite( tempFile.getAbsolutePath(), content ); 1148 1149 try 1150 { 1151 wagon.put( tempFile, "test-secured-put-resource" ); 1152 assertEquals( content, FileUtils.fileRead( sourceFile.getAbsolutePath() ) ); 1153 1154 checkRequestResponseForRedirectPutWithRelativeUrl( redirectHandler, putHandler ); 1155 } 1156 finally 1157 { 1158 wagon.disconnect(); 1159 tempFile.delete(); 1160 } 1161 1162 } 1163 finally 1164 { 1165 realServer.stop(); 1166 redirectServer.stop(); 1167 } 1168 } 1169 1170 1171 /** 1172 * 1173 */ 1174 @SuppressWarnings( "checkstyle:visibilitymodifier" ) 1175 public static class RedirectHandler 1176 extends AbstractHandler 1177 { 1178 String reason; 1179 1180 int retCode; 1181 1182 String redirectUrl; 1183 1184 File repositoryDirectory; 1185 1186 public List<HandlerRequestResponse> handlerRequestResponses = new ArrayList<HandlerRequestResponse>(); 1187 1188 RedirectHandler( String reason, int retCode, String redirectUrl, File repositoryDirectory ) 1189 { 1190 this.reason = reason; 1191 this.retCode = retCode; 1192 this.redirectUrl = redirectUrl; 1193 this.repositoryDirectory = repositoryDirectory; 1194 } 1195 1196 public void handle( String target, Request baseRequest, HttpServletRequest request, 1197 HttpServletResponse response ) throws IOException, ServletException 1198 { 1199 if ( request.getRequestURI().contains( "redirectRequest" ) ) 1200 { 1201 PutHandler putHandler = new PutHandler( this.repositoryDirectory ); 1202 putHandler.handle( target, baseRequest, request, response ); 1203 handlerRequestResponses.add( 1204 new HandlerRequestResponse( request.getMethod(), response.getStatus(), 1205 request.getRequestURI() ) ); 1206 return; 1207 } 1208 response.setStatus( this.retCode ); 1209 response.setHeader( "Location", this.redirectUrl + request.getRequestURI() ); 1210 baseRequest.setHandled( true ); 1211 1212 handlerRequestResponses.add( 1213 new HandlerRequestResponse( request.getMethod(), response.getStatus(), 1214 request.getRequestURI() ) ); 1215 } 1216 1217 1218 } 1219 1220 1221 private void runTestProxiedRequest( ProxyInfo proxyInfo, TestHeaderHandler handler ) 1222 throws Exception 1223 { 1224 // what an UGLY hack! 1225 // but apparently jetty needs some time to free up resources 1226 // <5s: broken test :( 1227 // CHECKSTYLE_OFF: MagicNumber 1228 Thread.sleep( 5001L ); 1229 // CHECKSTYLE_ON: MagicNumber 1230 1231 Server proxyServer = new Server( ); 1232 ServerConnector serverConnector = 1233 new ServerConnector( proxyServer, new HttpConnectionFactory( new HttpConfiguration() ) ); 1234 proxyServer.addConnector( serverConnector ); 1235 proxyServer.setHandler( handler ); 1236 1237 proxyServer.start(); 1238 1239 proxyInfo.setPort( getLocalPort( proxyServer ) ); 1240 1241 System.out.println( 1242 "start proxy on host/port " + proxyInfo.getHost() + "/" + proxyInfo.getPort() + " with non proxyHosts " 1243 + proxyInfo.getNonProxyHosts() ); 1244 1245 while ( !proxyServer.isRunning() || !proxyServer.isStarted() ) 1246 { 1247 Thread.sleep( 10 ); 1248 } 1249 1250 try 1251 { 1252 StreamingWagon wagon = (StreamingWagon) getWagon(); 1253 1254 Repository testRepository = new Repository( "id", "http://www.example.com/" ); 1255 1256 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString(); 1257 File sourceFile = new File( localRepositoryPath, "test-proxied-resource" ); 1258 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "content" ); 1259 1260 wagon.connect( testRepository, proxyInfo ); 1261 1262 try 1263 { 1264 wagon.getToStream( "test-proxied-resource", new ByteArrayOutputStream() ); 1265 1266 assertTrue( handler.headers.containsKey( "Proxy-Connection" ) ); 1267 } 1268 finally 1269 { 1270 System.setProperty( "http.proxyHost", "" ); 1271 System.setProperty( "http.proxyPort", "" ); 1272 wagon.disconnect(); 1273 } 1274 } 1275 finally 1276 { 1277 proxyServer.stop(); 1278 } 1279 } 1280 1281 private void runTestProxiedRequestWithProvider( ProxyInfoProvider proxyInfoProvider, TestHeaderHandler handler ) 1282 throws Exception 1283 { 1284 // what an UGLY hack! 1285 // but apparently jetty needs some time to free up resources 1286 // <5s: broken test :( 1287 // CHECKSTYLE_OFF: MagicNumber 1288 Thread.sleep( 5001L ); 1289 // CHECKSTYLE_ON: MagicNumber 1290 1291 Server proxyServer = new Server( ); 1292 ServerConnector serverConnector = 1293 new ServerConnector( proxyServer, new HttpConnectionFactory( new HttpConfiguration() ) ); 1294 proxyServer.addConnector( serverConnector ); 1295 1296 proxyServer.setHandler( handler ); 1297 1298 proxyServer.start(); 1299 1300 proxyInfoProvider.getProxyInfo( null ).setPort( getLocalPort( proxyServer ) ); 1301 1302 System.out.println( "start proxy on host/port " + proxyInfoProvider.getProxyInfo( null ).getHost() + "/" 1303 + proxyInfoProvider.getProxyInfo( null ).getPort() + " with non proxyHosts " 1304 + proxyInfoProvider.getProxyInfo( null ).getNonProxyHosts() ); 1305 1306 while ( !proxyServer.isRunning() || !proxyServer.isStarted() ) 1307 { 1308 Thread.sleep( 10 ); 1309 } 1310 1311 try 1312 { 1313 StreamingWagon wagon = (StreamingWagon) getWagon(); 1314 1315 Repository testRepository = new Repository( "id", "http://www.example.com/" ); 1316 1317 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString(); 1318 File sourceFile = new File( localRepositoryPath, "test-proxied-resource" ); 1319 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "content" ); 1320 1321 wagon.connect( testRepository, proxyInfoProvider ); 1322 1323 try 1324 { 1325 wagon.getToStream( "test-proxied-resource", new ByteArrayOutputStream() ); 1326 1327 assertTrue( handler.headers.containsKey( "Proxy-Connection" ) ); 1328 } 1329 finally 1330 { 1331 System.setProperty( "http.proxyHost", "" ); 1332 System.setProperty( "http.proxyPort", "" ); 1333 wagon.disconnect(); 1334 } 1335 } 1336 finally 1337 { 1338 proxyServer.stop(); 1339 } 1340 } 1341 1342 private ProxyInfo createProxyInfo() 1343 { 1344 ProxyInfo proxyInfo = new ProxyInfo(); 1345 proxyInfo.setHost( "localhost" ); 1346 proxyInfo.setNonProxyHosts( null ); 1347 proxyInfo.setType( "http" ); 1348 return proxyInfo; 1349 } 1350 1351 public void testSecuredGetUnauthorized() 1352 throws Exception 1353 { 1354 try 1355 { 1356 runTestSecuredGet( null ); 1357 fail(); 1358 } 1359 catch ( AuthorizationException e ) 1360 { 1361 assertTrue( true ); 1362 } 1363 } 1364 1365 public void testSecuredGetWrongPassword() 1366 throws Exception 1367 { 1368 try 1369 { 1370 AuthenticationInfo authInfo = new AuthenticationInfo(); 1371 authInfo.setUserName( "user" ); 1372 authInfo.setPassword( "admin" ); 1373 runTestSecuredGet( authInfo ); 1374 fail(); 1375 } 1376 catch ( AuthorizationException e ) 1377 { 1378 assertTrue( true ); 1379 } 1380 } 1381 1382 public void testSecuredGet() 1383 throws Exception 1384 { 1385 AuthenticationInfo authInfo = new AuthenticationInfo(); 1386 authInfo.setUserName( "user" ); 1387 authInfo.setPassword( "secret" ); 1388 runTestSecuredGet( authInfo ); 1389 } 1390 1391 1392 public void runTestSecuredGet( AuthenticationInfo authInfo ) 1393 throws Exception 1394 { 1395 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString(); 1396 Server server = createSecurityServer( localRepositoryPath ); 1397 1398 server.start(); 1399 1400 try 1401 { 1402 StreamingWagon wagon = (StreamingWagon) getWagon(); 1403 1404 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) ); 1405 1406 File sourceFile = new File( localRepositoryPath, "test-secured-resource" ); 1407 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "top secret" ); 1408 1409 wagon.connect( testRepository, authInfo ); 1410 1411 File file = File.createTempFile( "wagon-test", "txt" ); 1412 1413 try 1414 { 1415 wagon.get( "test-secured-resource", file ); 1416 } 1417 finally 1418 { 1419 wagon.disconnect(); 1420 } 1421 1422 FileInputStream in = new FileInputStream( file ); 1423 1424 assertEquals( "top secret", IOUtil.toString( in ) ); 1425 1426 /* 1427 * We need to wait a bit for all Jetty workers/threads to complete their work. Otherwise 1428 * we may suffer from race conditions where handlerRequestResponses list is not completely 1429 * populated and its premature iteration in testPreemptiveAuthenticationGet will lead to 1430 * a test failure. 1431 */ 1432 // CHECKSTYLE_OFF: MagicNumber 1433 Thread.sleep ( 2000L ); 1434 // CHECKSTYLE_ON: MagicNumber 1435 1436 TestSecurityHandler securityHandler = server.getChildHandlerByClass( TestSecurityHandler.class ); 1437 testPreemptiveAuthenticationGet( securityHandler, supportPreemptiveAuthenticationGet() ); 1438 1439 } 1440 finally 1441 { 1442 server.stop(); 1443 } 1444 } 1445 1446 1447 public void testSecuredGetToStream() 1448 throws Exception 1449 { 1450 AuthenticationInfo authInfo = new AuthenticationInfo(); 1451 authInfo.setUserName( "user" ); 1452 authInfo.setPassword( "secret" ); 1453 runTestSecuredGetToStream( authInfo ); 1454 } 1455 1456 public void runTestSecuredGetToStream( AuthenticationInfo authInfo ) 1457 throws Exception 1458 { 1459 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString(); 1460 Server server = createSecurityServer( localRepositoryPath ); 1461 1462 server.start(); 1463 1464 try 1465 { 1466 StreamingWagon wagon = (StreamingWagon) getWagon(); 1467 1468 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) ); 1469 1470 File sourceFile = new File( localRepositoryPath, "test-secured-resource" ); 1471 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "top secret" ); 1472 1473 wagon.connect( testRepository, authInfo ); 1474 1475 ByteArrayOutputStream out = new ByteArrayOutputStream(); 1476 try 1477 { 1478 wagon.getToStream( "test-secured-resource", out ); 1479 } 1480 finally 1481 { 1482 wagon.disconnect(); 1483 } 1484 1485 assertEquals( "top secret", out.toString( "US-ASCII" ) ); 1486 1487 /* 1488 * We need to wait a bit for all Jetty workers/threads to complete their work. Otherwise 1489 * we may suffer from race conditions where handlerRequestResponses list is not completely 1490 * populated and its premature iteration in testPreemptiveAuthenticationGet will lead to 1491 * a test failure. 1492 */ 1493 // CHECKSTYLE_OFF: MagicNumber 1494 Thread.sleep ( 2000L ); 1495 // CHECKSTYLE_ON: MagicNumber 1496 1497 TestSecurityHandler securityHandler = server.getChildHandlerByClass( TestSecurityHandler.class ); 1498 testPreemptiveAuthenticationGet( securityHandler, supportPreemptiveAuthenticationGet() ); 1499 } 1500 finally 1501 { 1502 server.stop(); 1503 } 1504 } 1505 1506 public void testSecuredResourceExistsUnauthorized() 1507 throws Exception 1508 { 1509 try 1510 { 1511 runTestSecuredResourceExists( null ); 1512 fail(); 1513 } 1514 catch ( AuthorizationException e ) 1515 { 1516 assertTrue( true ); 1517 } 1518 } 1519 1520 public void testSecuredResourceExistsWrongPassword() 1521 throws Exception 1522 { 1523 try 1524 { 1525 AuthenticationInfo authInfo = new AuthenticationInfo(); 1526 authInfo.setUserName( "user" ); 1527 authInfo.setPassword( "admin" ); 1528 runTestSecuredResourceExists( authInfo ); 1529 } 1530 catch ( AuthorizationException e ) 1531 { 1532 assertTrue( true ); 1533 } 1534 } 1535 1536 public void testSecuredResourceExists() 1537 throws Exception 1538 { 1539 AuthenticationInfo authInfo = new AuthenticationInfo(); 1540 authInfo.setUserName( "user" ); 1541 authInfo.setPassword( "secret" ); 1542 runTestSecuredResourceExists( authInfo ); 1543 } 1544 1545 public void runTestSecuredResourceExists( AuthenticationInfo authInfo ) 1546 throws Exception 1547 { 1548 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString(); 1549 Server server = createSecurityServer( localRepositoryPath ); 1550 1551 server.start(); 1552 1553 try 1554 { 1555 StreamingWagon wagon = (StreamingWagon) getWagon(); 1556 1557 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) ); 1558 1559 File sourceFile = new File( localRepositoryPath, "test-secured-resource-exists" ); 1560 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "top secret" ); 1561 1562 wagon.connect( testRepository, authInfo ); 1563 1564 try 1565 { 1566 assertTrue( wagon.resourceExists( "test-secured-resource-exists" ) ); 1567 1568 assertFalse( wagon.resourceExists( "test-secured-resource-not-exists" ) ); 1569 } 1570 finally 1571 { 1572 wagon.disconnect(); 1573 } 1574 } 1575 finally 1576 { 1577 server.stop(); 1578 } 1579 } 1580 1581 private Server createSecurityServer( String localRepositoryPath ) 1582 { 1583 Server server = new Server( ); 1584 1585 SecurityHandler sh = createSecurityHandler(); 1586 1587 ServletContextHandler root = new ServletContextHandler( ServletContextHandler.SESSIONS 1588 | ServletContextHandler.SECURITY ); 1589 root.setResourceBase( localRepositoryPath ); 1590 root.setSecurityHandler( sh ); 1591 ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); 1592 root.addServlet( servletHolder, "/*" ); 1593 1594 server.setHandler( root ); 1595 addConnector( server ); 1596 return server; 1597 } 1598 1599 private Server createStatusServer( int status ) 1600 { 1601 Server server = new Server( ); 1602 StatusHandler handler = new StatusHandler(); 1603 handler.setStatusToReturn( status ); 1604 server.setHandler( handler ); 1605 addConnector( server ); 1606 return server; 1607 } 1608 1609 1610 private String writeTestFile( File parent, String child, String compressionType ) 1611 throws IOException 1612 { 1613 File file = new File( parent, child ); 1614 file.getParentFile().mkdirs(); 1615 file.deleteOnExit(); 1616 OutputStream out = new FileOutputStream( file ); 1617 try 1618 { 1619 out.write( child.getBytes() ); 1620 } 1621 finally 1622 { 1623 out.close(); 1624 } 1625 1626 String ext = ""; 1627 if ( "gzip".equals( compressionType ) ) 1628 { 1629 ext = ".gz"; 1630 } 1631 if ( "deflate".equals( compressionType ) ) 1632 { 1633 ext = ".deflate"; 1634 } 1635 1636 file = new File( parent, child + ext ); 1637 file.deleteOnExit(); 1638 String content; 1639 out = new FileOutputStream( file ); 1640 if ( "gzip".equals( compressionType ) ) 1641 { 1642 out = new GZIPOutputStream( out ); 1643 } 1644 if ( "deflate".equals( compressionType ) ) 1645 { 1646 out = new DeflaterOutputStream( out ); 1647 } 1648 try 1649 { 1650 // write out different data than non-compressed file, so we can 1651 // assert the compressed version was returned 1652 content = file.getAbsolutePath(); 1653 out.write( content.getBytes() ); 1654 } 1655 finally 1656 { 1657 out.close(); 1658 } 1659 1660 return content; 1661 } 1662 1663 public void testPutForbidden() 1664 throws Exception 1665 { 1666 try 1667 { 1668 runTestPut( HttpServletResponse.SC_FORBIDDEN ); 1669 fail(); 1670 } 1671 catch ( AuthorizationException e ) 1672 { 1673 assertTrue( true ); 1674 } 1675 } 1676 1677 public void testPut404() 1678 throws Exception 1679 { 1680 try 1681 { 1682 runTestPut( HttpServletResponse.SC_NOT_FOUND ); 1683 fail(); 1684 } 1685 catch ( ResourceDoesNotExistException e ) 1686 { 1687 assertTrue( true ); 1688 } 1689 } 1690 1691 public void testPut500() 1692 throws Exception 1693 { 1694 try 1695 { 1696 runTestPut( HttpServletResponse.SC_INTERNAL_SERVER_ERROR ); 1697 fail(); 1698 } 1699 catch ( TransferFailedException e ) 1700 { 1701 assertTrue( true ); 1702 } 1703 } 1704 1705 public void testPut429() 1706 throws Exception 1707 { 1708 1709 try 1710 { 1711 1712 StreamingWagon wagon = (StreamingWagon) getWagon(); 1713 Server server = new Server( ); 1714 final AtomicBoolean called = new AtomicBoolean(); 1715 1716 AbstractHandler handler = new AbstractHandler() 1717 { 1718 public void handle( String target, Request baseRequest, HttpServletRequest request, 1719 HttpServletResponse response ) throws IOException, ServletException 1720 { 1721 if ( called.get() ) 1722 { 1723 response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR ); 1724 baseRequest.setHandled( true ); 1725 } 1726 else 1727 { 1728 called.set( true ); 1729 response.setStatus( SC_TOO_MANY_REQUESTS ); 1730 baseRequest.setHandled( true ); 1731 } 1732 } 1733 }; 1734 1735 server.setHandler( handler ); 1736 addConnector( server ); 1737 server.start(); 1738 1739 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) ); 1740 1741 File tempFile = File.createTempFile( "wagon", "tmp" ); 1742 tempFile.deleteOnExit(); 1743 FileUtils.fileWrite( tempFile.getAbsolutePath(), "content" ); 1744 1745 try 1746 { 1747 wagon.put( tempFile, "resource" ); 1748 fail(); 1749 } 1750 finally 1751 { 1752 wagon.disconnect(); 1753 1754 server.stop(); 1755 1756 tempFile.delete(); 1757 } 1758 1759 } 1760 catch ( TransferFailedException e ) 1761 { 1762 assertTrue( true ); 1763 } 1764 } 1765 1766 1767 private void runTestPut( int status ) 1768 throws Exception 1769 { 1770 StreamingWagon wagon = (StreamingWagon) getWagon(); 1771 1772 Server server = createStatusServer( status ); 1773 server.start(); 1774 1775 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) ); 1776 1777 File tempFile = File.createTempFile( "wagon", "tmp" ); 1778 tempFile.deleteOnExit(); 1779 FileUtils.fileWrite( tempFile.getAbsolutePath(), "content" ); 1780 1781 String baseUrl = getRepositoryUrl( server ); 1782 String resourceName = "resource"; 1783 String serverReasonPhrase = HttpStatus.getCode( status ).getMessage(); 1784 1785 try 1786 { 1787 wagon.put( tempFile, resourceName ); 1788 fail(); 1789 } 1790 catch ( Exception e ) 1791 { 1792 verifyWagonExceptionMessage( e, status, baseUrl + "/" + resourceName, serverReasonPhrase ); 1793 throw e; 1794 } 1795 finally 1796 { 1797 wagon.disconnect(); 1798 1799 server.stop(); 1800 1801 tempFile.delete(); 1802 } 1803 } 1804 1805 public void testSecuredPutUnauthorized() 1806 throws Exception 1807 { 1808 try 1809 { 1810 runTestSecuredPut( null ); 1811 fail(); 1812 } 1813 catch ( TransferFailedException e ) 1814 { 1815 assertTrue( true ); 1816 } 1817 } 1818 1819 public void testSecuredPutWrongPassword() 1820 throws Exception 1821 { 1822 try 1823 { 1824 AuthenticationInfo authInfo = new AuthenticationInfo(); 1825 authInfo.setUserName( "user" ); 1826 authInfo.setPassword( "admin" ); 1827 runTestSecuredPut( authInfo ); 1828 fail(); 1829 } 1830 catch ( TransferFailedException e ) 1831 { 1832 assertTrue( true ); 1833 } 1834 } 1835 1836 public void testSecuredPut() 1837 throws Exception 1838 { 1839 AuthenticationInfo authInfo = new AuthenticationInfo(); 1840 authInfo.setUserName( "user" ); 1841 authInfo.setPassword( "secret" ); 1842 runTestSecuredPut( authInfo ); 1843 } 1844 1845 public void runTestSecuredPut( AuthenticationInfo authInfo ) 1846 throws Exception 1847 { 1848 runTestSecuredPut( authInfo, 1 ); 1849 } 1850 1851 public void runTestSecuredPut( AuthenticationInfo authInfo, int putNumber ) 1852 throws Exception 1853 { 1854 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString(); 1855 Server server = new Server( ); 1856 1857 TestSecurityHandler sh = createSecurityHandler(); 1858 1859 PutHandler putHandler = new PutHandler( new File( localRepositoryPath ) ); 1860 1861 sh.setHandler( putHandler ); 1862 server.setHandler( sh ); 1863 addConnector( server ); 1864 server.start(); 1865 1866 StreamingWagon wagon = (StreamingWagon) getWagon(); 1867 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) ); 1868 wagon.connect( testRepository, authInfo ); 1869 try 1870 { 1871 for ( int i = 0; i < putNumber; i++ ) 1872 { 1873 File sourceFile = new File( localRepositoryPath, "test-secured-put-resource" ); 1874 sourceFile.delete(); 1875 assertFalse( sourceFile.exists() ); 1876 1877 File tempFile = File.createTempFile( "wagon", "tmp" ); 1878 tempFile.deleteOnExit(); 1879 FileUtils.fileWrite( tempFile.getAbsolutePath(), "put top secret" ); 1880 1881 try 1882 { 1883 wagon.put( tempFile, "test-secured-put-resource" ); 1884 } 1885 finally 1886 { 1887 tempFile.delete(); 1888 } 1889 1890 assertEquals( "put top secret", FileUtils.fileRead( sourceFile.getAbsolutePath() ) ); 1891 } 1892 } 1893 finally 1894 { 1895 wagon.disconnect(); 1896 server.stop(); 1897 } 1898 assertEquals( putNumber, putHandler.putCallNumber ); 1899 testPreemptiveAuthenticationPut( sh, supportPreemptiveAuthenticationPut() ); 1900 } 1901 1902 public void testNonSecuredPutFromStream() 1903 throws Exception 1904 { 1905 AuthenticationInfo authInfo = new AuthenticationInfo(); 1906 authInfo.setUserName( "user" ); 1907 authInfo.setPassword( "secret" ); 1908 runTestSecuredPutFromStream( authInfo, 1, false ); 1909 } 1910 1911 public void testSecuredPutFromStream() 1912 throws Exception 1913 { 1914 AuthenticationInfo authInfo = new AuthenticationInfo(); 1915 authInfo.setUserName( "user" ); 1916 authInfo.setPassword( "secret" ); 1917 runTestSecuredPutFromStream( authInfo, 1, true ); 1918 } 1919 1920 public void runTestSecuredPutFromStream( AuthenticationInfo authInfo, int putNumber, boolean addSecurityHandler ) 1921 throws Exception 1922 { 1923 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString(); 1924 Server server = new Server( ); 1925 1926 TestSecurityHandler sh = createSecurityHandler(); 1927 1928 PutHandler putHandler = new PutHandler( new File( localRepositoryPath ) ); 1929 1930 if ( addSecurityHandler ) 1931 { 1932 sh.setHandler( putHandler ); 1933 server.setHandler( sh ); 1934 } 1935 else 1936 { 1937 server.setHandler( putHandler ); 1938 } 1939 addConnector( server ); 1940 server.start(); 1941 1942 StreamingWagon wagon = (StreamingWagon) getWagon(); 1943 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) ); 1944 if ( addSecurityHandler ) 1945 { 1946 wagon.connect( testRepository, authInfo ); 1947 } 1948 else 1949 { 1950 wagon.connect( testRepository ); 1951 } 1952 try 1953 { 1954 for ( int i = 0; i < putNumber; i++ ) 1955 { 1956 File sourceFile = new File( localRepositoryPath, "test-secured-put-resource" ); 1957 sourceFile.delete(); 1958 assertFalse( sourceFile.exists() ); 1959 1960 File tempFile = File.createTempFile( "wagon", "tmp" ); 1961 tempFile.deleteOnExit(); 1962 String content = "put top secret"; 1963 FileUtils.fileWrite( tempFile.getAbsolutePath(), content ); 1964 1965 try ( FileInputStream fileInputStream = new FileInputStream( tempFile ) ) 1966 { 1967 wagon.putFromStream( fileInputStream, "test-secured-put-resource", content.length(), -1 ); 1968 } 1969 finally 1970 { 1971 tempFile.delete(); 1972 } 1973 1974 assertEquals( content, FileUtils.fileRead( sourceFile.getAbsolutePath() ) ); 1975 } 1976 } 1977 finally 1978 { 1979 wagon.disconnect(); 1980 server.stop(); 1981 } 1982 assertEquals( putNumber, putHandler.putCallNumber ); 1983 if ( addSecurityHandler ) 1984 { 1985 testPreemptiveAuthenticationPut( sh, supportPreemptiveAuthenticationPut() ); 1986 } 1987 1988 // ensure we didn't use chunked transfer which doesn't work on ngnix 1989 for ( DeployedResource deployedResource : putHandler.deployedResources ) 1990 { 1991 if ( StringUtils.equalsIgnoreCase( "chunked", deployedResource.transferEncoding ) ) 1992 { 1993 fail( "deployedResource use chunked: " + deployedResource ); 1994 } 1995 } 1996 } 1997 1998 1999 protected abstract boolean supportPreemptiveAuthenticationPut(); 2000 2001 protected abstract boolean supportPreemptiveAuthenticationGet(); 2002 2003 protected abstract boolean supportProxyPreemptiveAuthentication(); 2004 2005 protected void testPreemptiveAuthenticationGet( TestSecurityHandler sh, boolean preemptive ) 2006 { 2007 testPreemptiveAuthentication( sh, preemptive, HttpServletResponse.SC_OK ); 2008 } 2009 2010 protected void testPreemptiveAuthenticationPut( TestSecurityHandler sh, boolean preemptive ) 2011 { 2012 testPreemptiveAuthentication( sh, preemptive, HttpServletResponse.SC_CREATED ); 2013 } 2014 2015 protected void testPreemptiveAuthentication( TestSecurityHandler sh, boolean preemptive, int statusCode ) 2016 { 2017 2018 if ( preemptive ) 2019 { 2020 assertEquals( "not 1 security handler use " + sh.handlerRequestResponses, 1, 2021 sh.handlerRequestResponses.size() ); 2022 assertEquals( statusCode, sh.handlerRequestResponses.get( 0 ).responseCode ); 2023 } 2024 else 2025 { 2026 assertEquals( "not 2 security handler use " + sh.handlerRequestResponses, 2, 2027 sh.handlerRequestResponses.size() ); 2028 assertEquals( HttpServletResponse.SC_UNAUTHORIZED, sh.handlerRequestResponses.get( 0 ).responseCode ); 2029 assertEquals( statusCode, sh.handlerRequestResponses.get( 1 ).responseCode ); 2030 2031 } 2032 } 2033 2034 static class StatusHandler 2035 extends AbstractHandler 2036 { 2037 private int status; 2038 2039 public void setStatusToReturn( int status ) 2040 { 2041 this.status = status; 2042 } 2043 2044 public void handle( String target, Request baseRequest, HttpServletRequest request, 2045 HttpServletResponse response ) throws IOException, ServletException 2046 { 2047 if ( status != 0 ) 2048 { 2049 response.setStatus( status ); 2050 baseRequest.setHandled( true ); 2051 } 2052 } 2053 } 2054 2055 static class DeployedResource 2056 { 2057 String httpMethod; 2058 2059 String requestUri; 2060 2061 String contentLength; 2062 2063 String transferEncoding; 2064 2065 DeployedResource() 2066 { 2067 // no op 2068 } 2069 2070 @Override 2071 public String toString() 2072 { 2073 final StringBuilder sb = new StringBuilder(); 2074 sb.append( "DeployedResource" ); 2075 sb.append( "{httpMethod='" ).append( httpMethod ).append( '\'' ); 2076 sb.append( ", requestUri='" ).append( requestUri ).append( '\'' ); 2077 sb.append( ", contentLength='" ).append( contentLength ).append( '\'' ); 2078 sb.append( ", transferEncoding='" ).append( transferEncoding ).append( '\'' ); 2079 sb.append( '}' ); 2080 return sb.toString(); 2081 } 2082 } 2083 2084 /** 2085 * 2086 */ 2087 @SuppressWarnings( "checkstyle:visibilitymodifier" ) 2088 public static class PutHandler 2089 extends AbstractHandler 2090 { 2091 private final File resourceBase; 2092 2093 public List<DeployedResource> deployedResources = new ArrayList<DeployedResource>(); 2094 2095 public int putCallNumber = 0; 2096 2097 public List<HandlerRequestResponse> handlerRequestResponses = new ArrayList<HandlerRequestResponse>(); 2098 2099 public PutHandler( File repositoryDirectory ) 2100 { 2101 this.resourceBase = repositoryDirectory; 2102 } 2103 2104 public void handle( String target, Request baseRequest, HttpServletRequest request, 2105 HttpServletResponse response ) throws IOException, ServletException 2106 { 2107 if ( baseRequest.isHandled() || !"PUT".equals( baseRequest.getMethod() ) ) 2108 { 2109 return; 2110 } 2111 2112 baseRequest.setHandled( true ); 2113 2114 File file = new File( resourceBase, URLDecoder.decode( request.getPathInfo() ) ); 2115 file.getParentFile().mkdirs(); 2116 OutputStream out = null; 2117 InputStream in = null; 2118 try 2119 { 2120 in = request.getInputStream(); 2121 out = new FileOutputStream( file ); 2122 IOUtil.copy( in, out ); 2123 out.close(); 2124 out = null; 2125 in.close(); 2126 in = null; 2127 } 2128 finally 2129 { 2130 IOUtil.close( in ); 2131 IOUtil.close( out ); 2132 } 2133 putCallNumber++; 2134 DeployedResource deployedResource = new DeployedResource(); 2135 2136 deployedResource.httpMethod = request.getMethod(); 2137 deployedResource.requestUri = request.getRequestURI(); 2138 deployedResource.transferEncoding = request.getHeader( "Transfer-Encoding" ); 2139 deployedResource.contentLength = request.getHeader( "Content-Length" ); 2140 deployedResources.add( deployedResource ); 2141 2142 response.setStatus( HttpServletResponse.SC_CREATED ); 2143 2144 handlerRequestResponses.add( 2145 new HandlerRequestResponse( request.getMethod(), ( (Response) response ).getStatus(), 2146 request.getRequestURI() ) ); 2147 } 2148 } 2149 2150 private static class AuthorizingProxyHandler 2151 extends TestHeaderHandler 2152 { 2153 2154 List<HandlerRequestResponse> handlerRequestResponses = new ArrayList<HandlerRequestResponse>(); 2155 2156 public void handle( String target, Request baseRequest, HttpServletRequest request, 2157 HttpServletResponse response ) throws IOException, ServletException 2158 { 2159 System.out.println( " handle proxy request" ); 2160 if ( request.getHeader( "Proxy-Authorization" ) == null ) 2161 { 2162 handlerRequestResponses.add( 2163 new HandlerRequestResponse( request.getMethod(), 2164 HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED, 2165 request.getRequestURI() ) ); 2166 response.setStatus( HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED ); 2167 response.addHeader( "Proxy-Authenticate", "Basic realm=\"Squid proxy-caching web server\"" ); 2168 2169 baseRequest.setHandled( true ); 2170 return; 2171 } 2172 handlerRequestResponses.add( 2173 new HandlerRequestResponse( request.getMethod(), HttpServletResponse.SC_OK, request.getRequestURI() ) ); 2174 super.handle( target, baseRequest, request, response ); 2175 } 2176 } 2177 2178 /** 2179 * 2180 */ 2181 @SuppressWarnings( "checkstyle:visibilitymodifier" ) 2182 private static class TestHeaderHandler 2183 extends AbstractHandler 2184 { 2185 public Map<String, String> headers = Collections.emptyMap(); 2186 2187 public List<HandlerRequestResponse> handlerRequestResponses = new ArrayList<HandlerRequestResponse>(); 2188 2189 TestHeaderHandler() 2190 { 2191 } 2192 2193 public void handle( String target, Request baseRrequest, HttpServletRequest request, 2194 HttpServletResponse response ) throws IOException, ServletException 2195 { 2196 headers = new HashMap<String, String>(); 2197 for ( Enumeration<String> e = baseRrequest.getHeaderNames(); e.hasMoreElements(); ) 2198 { 2199 String name = e.nextElement(); 2200 Enumeration headerValues = baseRrequest.getHeaders( name ); 2201 // as per HTTP spec http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html 2202 // multiple values for the same header key are concatenated separated by comma 2203 // otherwise we wouldn't notice headers with same key added multiple times 2204 StringBuffer combinedHeaderValue = new StringBuffer(); 2205 for ( int i = 0; headerValues.hasMoreElements(); i++ ) 2206 { 2207 if ( i > 0 ) 2208 { 2209 combinedHeaderValue.append( "," ); 2210 } 2211 combinedHeaderValue.append( headerValues.nextElement() ); 2212 } 2213 headers.put( name, combinedHeaderValue.toString() ); 2214 } 2215 2216 response.setContentType( "text/plain" ); 2217 response.setStatus( HttpServletResponse.SC_OK ); 2218 response.getWriter().print( "Hello, World!" ); 2219 2220 handlerRequestResponses.add( 2221 new HandlerRequestResponse( baseRrequest.getMethod(), ( (Response) response ).getStatus(), 2222 baseRrequest.getRequestURI() ) ); 2223 2224 baseRrequest.setHandled( true ); 2225 } 2226 2227 } 2228 2229 protected TestSecurityHandler createSecurityHandler() 2230 { 2231 Constraint constraint = new Constraint(); 2232 constraint.setName( Constraint.__BASIC_AUTH ); 2233 constraint.setRoles( new String[]{ "admin" } ); 2234 constraint.setAuthenticate( true ); 2235 2236 ConstraintMapping cm = new ConstraintMapping(); 2237 cm.setConstraint( constraint ); 2238 cm.setPathSpec( "/*" ); 2239 2240 TestSecurityHandler sh = new TestSecurityHandler(); 2241 HashLoginService hashLoginService = new HashLoginService( "MyRealm" ); 2242 hashLoginService.putUser( "user", new Password( "secret" ), new String[] { "admin" } ); 2243 sh.setLoginService( hashLoginService ); 2244 sh.setConstraintMappings( new ConstraintMapping[]{ cm } ); 2245 sh.setAuthenticator ( new BasicAuthenticator() ); 2246 return sh; 2247 } 2248 2249 /** 2250 * 2251 */ 2252 @SuppressWarnings( "checkstyle:visibilitymodifier" ) 2253 public static class TestSecurityHandler 2254 extends ConstraintSecurityHandler 2255 { 2256 2257 public List<HandlerRequestResponse> handlerRequestResponses = new ArrayList<HandlerRequestResponse>(); 2258 2259 @Override 2260 public void handle( String target, Request baseRequest, HttpServletRequest request, 2261 HttpServletResponse response ) throws IOException, ServletException 2262 { 2263 String method = request.getMethod(); 2264 super.handle( target, baseRequest, request, response ); 2265 2266 handlerRequestResponses.add( 2267 new HandlerRequestResponse( method, ( (Response) response ).getStatus(), request.getRequestURI() ) ); 2268 } 2269 } 2270 2271 /** 2272 * 2273 */ 2274 @SuppressWarnings( "checkstyle:visibilitymodifier" ) 2275 public static class HandlerRequestResponse 2276 { 2277 public String method; 2278 2279 public int responseCode; 2280 2281 public String requestUri; 2282 2283 private HandlerRequestResponse( String method, int responseCode, String requestUri ) 2284 { 2285 this.method = method; 2286 this.responseCode = responseCode; 2287 this.requestUri = requestUri; 2288 } 2289 2290 @Override 2291 public String toString() 2292 { 2293 final StringBuilder sb = new StringBuilder(); 2294 sb.append( "HandlerRequestResponse" ); 2295 sb.append( "{method='" ).append( method ).append( '\'' ); 2296 sb.append( ", responseCode=" ).append( responseCode ); 2297 sb.append( ", requestUri='" ).append( requestUri ).append( '\'' ); 2298 sb.append( '}' ); 2299 return sb.toString(); 2300 } 2301 } 2302 2303 /** 2304 * Verify a WagonException message contains required format and context based on the status code we expected to 2305 * trigger it in the first place. 2306 * <p> 2307 * This implementation represents the most desired assertions, but HttpWagonTestCase sub-classes could override 2308 * this method if a specific wagon representation makes it impossible to meet these assertions. 2309 * 2310 * @param e an instance of {@link WagonException} 2311 * @param forStatusCode the response status code that triggered the exception 2312 * @param forUrl the url that triggered the exception 2313 * @param forReasonPhrase the optional status line reason phrase the server returned 2314 */ 2315 protected void verifyWagonExceptionMessage( Exception e, int forStatusCode, String forUrl, String forReasonPhrase ) 2316 { 2317 // TODO: handle AuthenticationException for Wagon.connect() calls 2318 assertNotNull( e ); 2319 try 2320 { 2321 assertTrue( "only verify instances of WagonException", e instanceof WagonException ); 2322 2323 String reasonPhrase; 2324 String assertMessageForBadMessage = "exception message not described properly"; 2325 switch ( forStatusCode ) 2326 { 2327 case HttpServletResponse.SC_NOT_FOUND: 2328 // TODO: add test for 410: Gone? 2329 assertTrue( "404 not found response should throw ResourceDoesNotExistException", 2330 e instanceof ResourceDoesNotExistException ); 2331 reasonPhrase = StringUtils.isEmpty( forReasonPhrase ) ? " Not Found" : ( " " + forReasonPhrase ); 2332 assertEquals( assertMessageForBadMessage, "Resource missing at " + forUrl + " 404" 2333 + reasonPhrase, e.getMessage() ); 2334 break; 2335 2336 case HttpServletResponse.SC_UNAUTHORIZED: 2337 // FIXME assumes Wagon.get()/put() returning 401 instead of Wagon.connect() 2338 assertTrue( "401 Unauthorized should throw AuthorizationException since " 2339 + " AuthenticationException is not explicitly declared as thrown from wagon " 2340 + "methods", 2341 e instanceof AuthorizationException ); 2342 reasonPhrase = StringUtils.isEmpty( forReasonPhrase ) ? " Unauthorized" : ( " " + forReasonPhrase ); 2343 assertEquals( assertMessageForBadMessage, "Authentication failed for " + forUrl + " 401" 2344 + reasonPhrase, e.getMessage() ); 2345 break; 2346 2347 case HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED: 2348 assertTrue( "407 Proxy authentication required should throw AuthorizationException", 2349 e instanceof AuthorizationException ); 2350 reasonPhrase = StringUtils.isEmpty( forReasonPhrase ) ? " Proxy Authentication Required" 2351 : ( " " + forReasonPhrase ); 2352 assertEquals( assertMessageForBadMessage, "HTTP proxy server authentication failed for " 2353 + forUrl + " 407" + reasonPhrase, e.getMessage() ); 2354 break; 2355 2356 case HttpServletResponse.SC_FORBIDDEN: 2357 assertTrue( "403 Forbidden should throw AuthorizationException", 2358 e instanceof AuthorizationException ); 2359 reasonPhrase = StringUtils.isEmpty( forReasonPhrase ) ? " Forbidden" : ( " " + forReasonPhrase ); 2360 assertEquals( assertMessageForBadMessage, "Authorization failed for " + forUrl + " 403" 2361 + reasonPhrase, e.getMessage() ); 2362 break; 2363 2364 default: 2365 assertTrue( "transfer failures should at least be wrapped in a TransferFailedException", e 2366 instanceof TransferFailedException ); 2367 assertTrue( "expected status code for transfer failures should be >= 400", 2368 forStatusCode >= HttpServletResponse.SC_BAD_REQUEST ); 2369 reasonPhrase = forReasonPhrase == null ? "" : " " + forReasonPhrase; 2370 assertEquals( assertMessageForBadMessage, "Transfer failed for " + forUrl + " " 2371 + forStatusCode + reasonPhrase, e.getMessage() ); 2372 break; 2373 } 2374 } 2375 catch ( AssertionError assertionError ) 2376 { 2377 logger.error( "Exception which failed assertions: ", e ); 2378 throw assertionError; 2379 } 2380 2381 } 2382 2383}