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