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