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