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