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