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