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