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