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