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.repository.Repository;
32 import org.apache.maven.wagon.resource.Resource;
33 import org.codehaus.plexus.util.FileUtils;
34 import org.codehaus.plexus.util.IOUtil;
35 import org.codehaus.plexus.util.StringOutputStream;
36 import org.mortbay.jetty.Handler;
37 import org.mortbay.jetty.HttpConnection;
38 import org.mortbay.jetty.Request;
39 import org.mortbay.jetty.Response;
40 import org.mortbay.jetty.Server;
41 import org.mortbay.jetty.handler.AbstractHandler;
42 import org.mortbay.jetty.handler.HandlerCollection;
43 import org.mortbay.jetty.security.Constraint;
44 import org.mortbay.jetty.security.ConstraintMapping;
45 import org.mortbay.jetty.security.HashUserRealm;
46 import org.mortbay.jetty.security.SecurityHandler;
47 import org.mortbay.jetty.servlet.Context;
48 import org.mortbay.jetty.servlet.DefaultServlet;
49 import org.mortbay.jetty.servlet.ServletHolder;
50
51 import javax.servlet.ServletException;
52 import javax.servlet.ServletInputStream;
53 import javax.servlet.http.HttpServletRequest;
54 import javax.servlet.http.HttpServletResponse;
55 import java.io.File;
56 import java.io.FileInputStream;
57 import java.io.FileOutputStream;
58 import java.io.IOException;
59 import java.io.OutputStream;
60 import java.lang.reflect.Method;
61 import java.net.URLDecoder;
62 import java.util.ArrayList;
63 import java.util.Collections;
64 import java.util.Enumeration;
65 import java.util.HashMap;
66 import java.util.List;
67 import java.util.Map;
68 import java.util.Properties;
69 import java.util.zip.GZIPOutputStream;
70
71
72
73
74 public abstract class HttpWagonTestCase
75 extends StreamingWagonTestCase
76 {
77 private Server server;
78
79 protected void setupWagonTestingFixtures()
80 throws Exception
81 {
82
83
84 File file = FileTestUtils.createUniqueFile( "local-repository", "test-resource" );
85
86 file.delete();
87
88 file.getParentFile().mkdirs();
89
90 File repositoryDirectory = getRepositoryDirectory();
91 FileUtils.deleteDirectory( repositoryDirectory );
92 repositoryDirectory.mkdirs();
93
94 server = new Server( 0 );
95
96 PutHandler putHandler = new PutHandler( repositoryDirectory );
97 server.addHandler( putHandler );
98
99 createContext( server, repositoryDirectory );
100
101 addConnectors( server );
102
103 server.start();
104
105 testRepository.setUrl( getTestRepositoryUrl() );
106 }
107
108 @Override
109 protected final int getTestRepositoryPort()
110 {
111 if ( server == null )
112 {
113 return 0;
114 }
115 return server.getConnectors()[0].getLocalPort();
116 }
117
118 protected void createContext( Server server, File repositoryDirectory )
119 throws IOException
120 {
121 Context root = new Context( server, "/", Context.SESSIONS );
122 root.setResourceBase( repositoryDirectory.getAbsolutePath() );
123 ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
124 root.addServlet( servletHolder, "/*" );
125 }
126
127 protected void tearDownWagonTestingFixtures()
128 throws Exception
129 {
130 server.stop();
131 }
132
133 public void testWagonGetFileList()
134 throws Exception
135 {
136 File dir = getRepositoryDirectory();
137 FileUtils.deleteDirectory( dir );
138
139 File f = new File( dir, "file-list" );
140 f.mkdirs();
141
142 super.testWagonGetFileList();
143 }
144
145 public void testHttpHeaders()
146 throws Exception
147 {
148 Properties properties = new Properties();
149 properties.setProperty( "User-Agent", "Maven-Wagon/1.0" );
150
151 StreamingWagon wagon = (StreamingWagon) getWagon();
152
153 setHttpHeaders( wagon, properties );
154
155 Server server = new Server( 0 );
156 TestHeaderHandler handler = new TestHeaderHandler();
157 server.setHandler( handler );
158 addConnectors( server );
159 server.start();
160
161 wagon.connect(
162 new Repository( "id", getProtocol() + "://localhost:" + server.getConnectors()[0].getLocalPort() ) );
163
164 wagon.getToStream( "resource", new StringOutputStream() );
165
166 wagon.disconnect();
167
168 server.stop();
169
170 assertEquals( "Maven-Wagon/1.0", handler.headers.get( "User-Agent" ) );
171 }
172
173
174
175
176 public void testHttpHeadersWithCommonMethods()
177 throws Exception
178 {
179 Properties properties = new Properties();
180 properties.setProperty( "User-Agent", "Maven-Wagon/1.0" );
181
182 StreamingWagon wagon = (StreamingWagon) getWagon();
183
184 Method setHttpHeaders = wagon.getClass().getMethod( "setHttpHeaders", Properties.class );
185 setHttpHeaders.invoke( wagon, properties );
186
187 Server server = new Server( 0 );
188 TestHeaderHandler handler = new TestHeaderHandler();
189 server.setHandler( handler );
190 addConnectors( server );
191 server.start();
192
193 wagon.connect(
194 new Repository( "id", getProtocol() + "://localhost:" + server.getConnectors()[0].getLocalPort() ) );
195
196 wagon.getToStream( "resource", new StringOutputStream() );
197
198 wagon.disconnect();
199
200 server.stop();
201
202 assertEquals( "Maven-Wagon/1.0", handler.headers.get( "User-Agent" ) );
203 }
204
205 protected abstract void setHttpHeaders( StreamingWagon wagon, Properties properties );
206
207 protected void addConnectors( Server server )
208 {
209 }
210
211 protected String getRepositoryUrl( Server server )
212 {
213 int localPort = server.getConnectors()[0].getLocalPort();
214 return getProtocol() + "://localhost:" + localPort;
215 }
216
217 public void testGetForbidden()
218 throws Exception
219 {
220 try
221 {
222 runTestGet( HttpServletResponse.SC_FORBIDDEN );
223 fail();
224 }
225 catch ( AuthorizationException e )
226 {
227 assertTrue( true );
228 }
229 }
230
231 public void testGet404()
232 throws Exception
233 {
234 try
235 {
236 runTestGet( HttpServletResponse.SC_NOT_FOUND );
237 fail();
238 }
239 catch ( ResourceDoesNotExistException e )
240 {
241 assertTrue( true );
242 }
243 }
244
245 public void testGet500()
246 throws Exception
247 {
248 try
249 {
250 runTestGet( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
251 fail();
252 }
253 catch ( TransferFailedException e )
254 {
255 assertTrue( true );
256 }
257 }
258
259 private void runTestGet( int status )
260 throws Exception
261 {
262 StreamingWagon wagon = (StreamingWagon) getWagon();
263
264 Server server = new Server( 0 );
265 StatusHandler handler = new StatusHandler();
266 handler.setStatusToReturn( status );
267 server.setHandler( handler );
268 addConnectors( server );
269 server.start();
270
271 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) );
272
273 try
274 {
275 wagon.getToStream( "resource", new StringOutputStream() );
276 fail();
277 }
278 finally
279 {
280 wagon.disconnect();
281
282 server.stop();
283 }
284 }
285
286 public void testResourceExistsForbidden()
287 throws Exception
288 {
289 try
290 {
291 runTestResourceExists( HttpServletResponse.SC_FORBIDDEN );
292 fail();
293 }
294 catch ( AuthorizationException e )
295 {
296 assertTrue( true );
297 }
298 }
299
300 public void testResourceExists404()
301 throws Exception
302 {
303 try
304 {
305 assertFalse( runTestResourceExists( HttpServletResponse.SC_NOT_FOUND ) );
306 }
307 catch ( ResourceDoesNotExistException e )
308 {
309 assertTrue( true );
310 }
311 }
312
313 public void testResourceExists500()
314 throws Exception
315 {
316 try
317 {
318 runTestResourceExists( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
319 fail();
320 }
321 catch ( TransferFailedException e )
322 {
323 assertTrue( true );
324 }
325 }
326
327 private boolean runTestResourceExists( int status )
328 throws Exception
329 {
330 StreamingWagon wagon = (StreamingWagon) getWagon();
331
332 Server server = new Server( 0 );
333 StatusHandler handler = new StatusHandler();
334 handler.setStatusToReturn( status );
335 server.setHandler( handler );
336 addConnectors( server );
337 server.start();
338
339 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) );
340
341 try
342 {
343 return wagon.resourceExists( "resource" );
344 }
345 finally
346 {
347 wagon.disconnect();
348
349 server.stop();
350 }
351 }
352
353 protected long getExpectedLastModifiedOnGet( Repository repository, Resource resource )
354 {
355 File file = new File( getRepositoryDirectory(), resource.getName() );
356 return ( file.lastModified() / 1000 ) * 1000;
357 }
358
359 protected File getRepositoryDirectory()
360 {
361 return getTestFile( "target/test-output/http-repository" );
362 }
363
364 public void testGzipGet()
365 throws Exception
366 {
367 Server server = new Server( getTestRepositoryPort() );
368
369 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
370 Context root = new Context( server, "/", Context.SESSIONS );
371 root.setResourceBase( localRepositoryPath );
372 ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
373 servletHolder.setInitParameter( "gzip", "true" );
374 root.addServlet( servletHolder, "/*" );
375 addConnectors( server );
376 server.start();
377
378 try
379 {
380 Wagon wagon = getWagon();
381
382 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) );
383
384 File sourceFile = new File( localRepositoryPath + "/gzip" );
385
386 sourceFile.deleteOnExit();
387
388 String resName = "gzip-res.txt";
389 String sourceContent = writeTestFileGzip( sourceFile, resName );
390
391 wagon.connect( testRepository );
392
393 File destFile = FileTestUtils.createUniqueFile( getName(), getName() );
394
395 destFile.deleteOnExit();
396
397 wagon.get( "gzip/" + resName, destFile );
398
399 wagon.disconnect();
400
401 String destContent = FileUtils.fileRead( destFile );
402
403 assertEquals( sourceContent, destContent );
404 }
405 finally
406 {
407 server.stop();
408 }
409 }
410
411 public void testProxiedRequest()
412 throws Exception
413 {
414 ProxyInfo proxyInfo = createProxyInfo();
415 TestHeaderHandler handler = new TestHeaderHandler();
416
417 runTestProxiedRequest( proxyInfo, handler );
418 }
419
420 public void testProxiedRequestWithAuthentication()
421 throws Exception
422 {
423 ProxyInfo proxyInfo = createProxyInfo();
424 proxyInfo.setUserName( "user" );
425 proxyInfo.setPassword( "secret" );
426 TestHeaderHandler handler = new AuthorizingProxyHandler();
427
428 runTestProxiedRequest( proxyInfo, handler );
429
430 assertTrue( handler.headers.containsKey( "Proxy-Authorization" ) );
431 }
432
433 private void runTestProxiedRequest( ProxyInfo proxyInfo, TestHeaderHandler handler )
434 throws Exception
435 {
436
437
438
439 Thread.sleep( 5001L );
440
441 Server proxyServer = new Server( 0 );
442
443 proxyServer.setHandler( handler );
444
445 proxyServer.start();
446
447 proxyInfo.setPort( proxyServer.getConnectors()[0].getLocalPort() );
448
449 System.out.println(
450 "start proxy on host/port " + proxyInfo.getHost() + "/" + proxyInfo.getPort() + " with non proxyHosts "
451 + proxyInfo.getNonProxyHosts() );
452
453 while ( !proxyServer.isRunning() || !proxyServer.isStarted() )
454 {
455 Thread.sleep( 10 );
456 }
457
458 try
459 {
460 StreamingWagon wagon = (StreamingWagon) getWagon();
461
462 System.out.println( " wagon hashCode " + wagon.hashCode() );
463
464 Repository testRepository = new Repository( "id", "http://www.example.com/" );
465
466 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
467 File sourceFile = new File( localRepositoryPath, "test-proxied-resource" );
468 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "content" );
469
470 wagon.connect( testRepository, proxyInfo );
471
472 StringOutputStream out = new StringOutputStream();
473 try
474 {
475 wagon.getToStream( "test-proxied-resource", out );
476
477 assertTrue( handler.headers.containsKey( "Proxy-Connection" ) );
478 }
479 finally
480 {
481 System.setProperty( "http.proxyHost", "" );
482 System.setProperty( "http.proxyPort", "" );
483 wagon.disconnect();
484 }
485 }
486 finally
487 {
488 proxyServer.stop();
489 }
490 }
491
492 private ProxyInfo createProxyInfo()
493 {
494 ProxyInfo proxyInfo = new ProxyInfo();
495 proxyInfo.setHost( "localhost" );
496 proxyInfo.setNonProxyHosts( null );
497 proxyInfo.setType( "http" );
498 return proxyInfo;
499 }
500
501 public void testSecuredGetUnauthorized()
502 throws Exception
503 {
504 try
505 {
506 runTestSecuredGet( null );
507 fail();
508 }
509 catch ( AuthorizationException e )
510 {
511 assertTrue( true );
512 }
513 }
514
515 public void testSecuredGetWrongPassword()
516 throws Exception
517 {
518 try
519 {
520 AuthenticationInfo authInfo = new AuthenticationInfo();
521 authInfo.setUserName( "user" );
522 authInfo.setPassword( "admin" );
523 runTestSecuredGet( authInfo );
524 fail();
525 }
526 catch ( AuthorizationException e )
527 {
528 assertTrue( true );
529 }
530 }
531
532 public void testSecuredGet()
533 throws Exception
534 {
535 AuthenticationInfo authInfo = new AuthenticationInfo();
536 authInfo.setUserName( "user" );
537 authInfo.setPassword( "secret" );
538 runTestSecuredGet( authInfo );
539 }
540
541 public void runTestSecuredGet( AuthenticationInfo authInfo )
542 throws Exception
543 {
544 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
545 Server server = createSecurityServer( localRepositoryPath );
546 server.start();
547
548 try
549 {
550 StreamingWagon wagon = (StreamingWagon) getWagon();
551
552 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) );
553
554 File sourceFile = new File( localRepositoryPath, "test-secured-resource" );
555 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "top secret" );
556
557 wagon.connect( testRepository, authInfo );
558
559 StringOutputStream out = new StringOutputStream();
560 try
561 {
562 wagon.getToStream( "test-secured-resource", out );
563 }
564 finally
565 {
566 wagon.disconnect();
567 }
568
569 assertEquals( "top secret", out.toString() );
570 }
571 finally
572 {
573 server.stop();
574 }
575 }
576
577 public void testSecuredResourceExistsUnauthorized()
578 throws Exception
579 {
580 try
581 {
582 runTestSecuredResourceExists( null );
583 fail();
584 }
585 catch ( AuthorizationException e )
586 {
587 assertTrue( true );
588 }
589 }
590
591 public void testSecuredResourceExistsWrongPassword()
592 throws Exception
593 {
594 try
595 {
596 AuthenticationInfo authInfo = new AuthenticationInfo();
597 authInfo.setUserName( "user" );
598 authInfo.setPassword( "admin" );
599 runTestSecuredResourceExists( authInfo );
600 }
601 catch ( AuthorizationException e )
602 {
603 assertTrue( true );
604 }
605 }
606
607 public void testSecuredResourceExists()
608 throws Exception
609 {
610 AuthenticationInfo authInfo = new AuthenticationInfo();
611 authInfo.setUserName( "user" );
612 authInfo.setPassword( "secret" );
613 runTestSecuredResourceExists( authInfo );
614 }
615
616 public void runTestSecuredResourceExists( AuthenticationInfo authInfo )
617 throws Exception
618 {
619 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
620 Server server = createSecurityServer( localRepositoryPath );
621 server.start();
622
623 try
624 {
625 StreamingWagon wagon = (StreamingWagon) getWagon();
626
627 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) );
628
629 File sourceFile = new File( localRepositoryPath, "test-secured-resource-exists" );
630 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "top secret" );
631
632 wagon.connect( testRepository, authInfo );
633
634 try
635 {
636 assertTrue( wagon.resourceExists( "test-secured-resource-exists" ) );
637
638 assertFalse( wagon.resourceExists( "test-secured-resource-not-exists" ) );
639 }
640 finally
641 {
642 wagon.disconnect();
643 }
644 }
645 finally
646 {
647 server.stop();
648 }
649 }
650
651 private Server createSecurityServer( String localRepositoryPath )
652 {
653 Server server = new Server( 0 );
654
655 SecurityHandler sh = createSecurityHandler();
656
657 Context root = new Context( Context.SESSIONS );
658 root.setContextPath( "/" );
659 root.addHandler( sh );
660 root.setResourceBase( localRepositoryPath );
661 ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
662 root.addServlet( servletHolder, "/*" );
663
664 server.setHandler( root );
665 addConnectors( server );
666 return server;
667 }
668
669
670 private String writeTestFileGzip( File parent, String child )
671 throws IOException
672 {
673 File file = new File( parent, child );
674 file.getParentFile().mkdirs();
675 file.deleteOnExit();
676 OutputStream out = new FileOutputStream( file );
677 try
678 {
679 out.write( child.getBytes() );
680 }
681 finally
682 {
683 out.close();
684 }
685
686 file = new File( parent, child + ".gz" );
687 file.deleteOnExit();
688 String content;
689 out = new FileOutputStream( file );
690 out = new GZIPOutputStream( out );
691 try
692 {
693
694
695 content = file.getAbsolutePath();
696 out.write( content.getBytes() );
697 }
698 finally
699 {
700 out.close();
701 }
702
703 return content;
704 }
705
706 public void testPutForbidden()
707 throws Exception
708 {
709 try
710 {
711 runTestPut( HttpServletResponse.SC_FORBIDDEN );
712 fail();
713 }
714 catch ( AuthorizationException e )
715 {
716 assertTrue( true );
717 }
718 }
719
720 public void testPut404()
721 throws Exception
722 {
723 try
724 {
725 runTestPut( HttpServletResponse.SC_NOT_FOUND );
726 fail();
727 }
728 catch ( ResourceDoesNotExistException e )
729 {
730 assertTrue( true );
731 }
732 }
733
734 public void testPut500()
735 throws Exception
736 {
737 try
738 {
739 runTestPut( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
740 fail();
741 }
742 catch ( TransferFailedException e )
743 {
744 assertTrue( true );
745 }
746 }
747
748 private void runTestPut( int status )
749 throws Exception
750 {
751 StreamingWagon wagon = (StreamingWagon) getWagon();
752
753 Server server = new Server( 0 );
754 StatusHandler handler = new StatusHandler();
755 handler.setStatusToReturn( status );
756 server.setHandler( handler );
757 addConnectors( server );
758 server.start();
759
760 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) );
761
762 File tempFile = File.createTempFile( "wagon", "tmp" );
763 tempFile.deleteOnExit();
764 FileUtils.fileWrite( tempFile.getAbsolutePath(), "content" );
765
766 try
767 {
768 wagon.put( tempFile, "resource" );
769 fail();
770 }
771 finally
772 {
773 wagon.disconnect();
774
775 server.stop();
776
777 tempFile.delete();
778 }
779 }
780
781 public void testSecuredPutUnauthorized()
782 throws Exception
783 {
784 try
785 {
786 runTestSecuredPut( null );
787 fail();
788 }
789 catch ( TransferFailedException e )
790 {
791 assertTrue( true );
792 }
793 }
794
795 public void testSecuredPutWrongPassword()
796 throws Exception
797 {
798 try
799 {
800 AuthenticationInfo authInfo = new AuthenticationInfo();
801 authInfo.setUserName( "user" );
802 authInfo.setPassword( "admin" );
803 runTestSecuredPut( authInfo );
804 fail();
805 }
806 catch ( TransferFailedException e )
807 {
808 assertTrue( true );
809 }
810 }
811
812 public void testSecuredPut()
813 throws Exception
814 {
815 AuthenticationInfo authInfo = new AuthenticationInfo();
816 authInfo.setUserName( "user" );
817 authInfo.setPassword( "secret" );
818 runTestSecuredPut( authInfo );
819 }
820
821 public void runTestSecuredPut( AuthenticationInfo authInfo )
822 throws Exception
823 {
824 runTestSecuredPut( authInfo, 1 );
825 }
826
827 public void runTestSecuredPut( AuthenticationInfo authInfo, int putNumber )
828 throws Exception
829 {
830 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
831 Server server = new Server( 0 );
832
833 TestSecurityHandler sh = createSecurityHandler();
834
835 PutHandler putHandler = new PutHandler( new File( localRepositoryPath ) );
836
837 HandlerCollection handlers = new HandlerCollection();
838 handlers.setHandlers( new Handler[]{ sh, putHandler } );
839
840 server.setHandler( handlers );
841 addConnectors( server );
842 server.start();
843
844 StreamingWagon wagon = (StreamingWagon) getWagon();
845 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) );
846 wagon.connect( testRepository, authInfo );
847 try
848 {
849 for ( int i = 0; i < putNumber; i++ )
850 {
851 File sourceFile = new File( localRepositoryPath, "test-secured-put-resource" );
852 sourceFile.delete();
853 assertFalse( sourceFile.exists() );
854
855 File tempFile = File.createTempFile( "wagon", "tmp" );
856 tempFile.deleteOnExit();
857 FileUtils.fileWrite( tempFile.getAbsolutePath(), "put top secret" );
858
859 try
860 {
861 wagon.put( tempFile, "test-secured-put-resource" );
862 }
863 finally
864 {
865 tempFile.delete();
866 }
867
868 assertEquals( "put top secret", FileUtils.fileRead( sourceFile.getAbsolutePath() ) );
869 }
870 }
871 finally
872 {
873 wagon.disconnect();
874 server.stop();
875 }
876 assertEquals( putNumber, putHandler.putCallNumber );
877 testPreemptiveAuthentication( sh );
878 }
879
880 public void testNonSecuredPutFromStream()
881 throws Exception
882 {
883 AuthenticationInfo authInfo = new AuthenticationInfo();
884 authInfo.setUserName( "user" );
885 authInfo.setPassword( "secret" );
886 runTestSecuredPutFromStream( authInfo, 1, false );
887 }
888
889 public void testSecuredPutFromStream()
890 throws Exception
891 {
892 AuthenticationInfo authInfo = new AuthenticationInfo();
893 authInfo.setUserName( "user" );
894 authInfo.setPassword( "secret" );
895 runTestSecuredPutFromStream( authInfo, 1, true );
896 }
897
898 public void runTestSecuredPutFromStream( AuthenticationInfo authInfo, int putNumber, boolean addSecurityHandler )
899 throws Exception
900 {
901 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
902 Server server = new Server( 0 );
903
904 TestSecurityHandler sh = createSecurityHandler();
905
906 PutHandler putHandler = new PutHandler( new File( localRepositoryPath ) );
907
908 HandlerCollection handlers = new HandlerCollection();
909 handlers.setHandlers( addSecurityHandler ? new Handler[]{ sh, putHandler } : new Handler[]{ putHandler } );
910
911 server.setHandler( handlers );
912 addConnectors( server );
913 server.start();
914
915 StreamingWagon wagon = (StreamingWagon) getWagon();
916 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) );
917 if ( addSecurityHandler )
918 {
919 wagon.connect( testRepository, authInfo );
920 }
921 else
922 {
923 wagon.connect( testRepository );
924 }
925 try
926 {
927 for ( int i = 0; i < putNumber; i++ )
928 {
929 File sourceFile = new File( localRepositoryPath, "test-secured-put-resource" );
930 sourceFile.delete();
931 assertFalse( sourceFile.exists() );
932
933 File tempFile = File.createTempFile( "wagon", "tmp" );
934 tempFile.deleteOnExit();
935 FileUtils.fileWrite( tempFile.getAbsolutePath(), "put top secret" );
936
937 FileInputStream fileInputStream = new FileInputStream( tempFile );
938 try
939 {
940 wagon.putFromStream( fileInputStream, "test-secured-put-resource" );
941 }
942 finally
943 {
944 fileInputStream.close();
945 tempFile.delete();
946
947 }
948
949 assertEquals( "put top secret", FileUtils.fileRead( sourceFile.getAbsolutePath() ) );
950 }
951 }
952 finally
953 {
954 wagon.disconnect();
955 server.stop();
956 }
957 assertEquals( putNumber, putHandler.putCallNumber );
958 if ( addSecurityHandler )
959 {
960 testPreemptiveAuthentication( sh );
961 }
962 }
963
964
965 protected abstract boolean supportPreemptiveAuthentication();
966
967 protected void testPreemptiveAuthentication( TestSecurityHandler sh )
968 {
969
970 if ( supportPreemptiveAuthentication() )
971 {
972 assertEquals( "not 1 security handler use " + sh.securityHandlerRequestReponses, 1,
973 sh.securityHandlerRequestReponses.size() );
974 assertEquals( 200, sh.securityHandlerRequestReponses.get( 0 ).responseCode );
975 }
976 else
977 {
978 assertEquals( "not 2 security handler use " + sh.securityHandlerRequestReponses, 2,
979 sh.securityHandlerRequestReponses.size() );
980 assertEquals( 401, sh.securityHandlerRequestReponses.get( 0 ).responseCode );
981 assertEquals( 200, sh.securityHandlerRequestReponses.get( 1 ).responseCode );
982
983 }
984 }
985
986 static class StatusHandler
987 extends AbstractHandler
988 {
989 private int status;
990
991 public void setStatusToReturn( int status )
992 {
993 this.status = status;
994 }
995
996 public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch )
997 throws IOException, ServletException
998 {
999 if ( status != 0 )
1000 {
1001 response.setStatus( status );
1002 ( (Request) request ).setHandled( true );
1003 }
1004 }
1005 }
1006
1007 static class PutHandler
1008 extends AbstractHandler
1009 {
1010 private final File resourceBase;
1011
1012 public int putCallNumber = 0;
1013
1014 public PutHandler( File repositoryDirectory )
1015 {
1016 this.resourceBase = repositoryDirectory;
1017 }
1018
1019 public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch )
1020 throws IOException, ServletException
1021 {
1022 Request base_request =
1023 request instanceof Request ? (Request) request : HttpConnection.getCurrentConnection().getRequest();
1024
1025 if ( base_request.isHandled() || !"PUT".equals( base_request.getMethod() ) )
1026 {
1027 return;
1028 }
1029
1030 base_request.setHandled( true );
1031
1032 File file = new File( resourceBase, URLDecoder.decode( request.getPathInfo() ) );
1033 file.getParentFile().mkdirs();
1034 FileOutputStream out = new FileOutputStream( file );
1035 ServletInputStream in = request.getInputStream();
1036 try
1037 {
1038 IOUtil.copy( in, out );
1039 }
1040 finally
1041 {
1042 in.close();
1043 out.close();
1044 }
1045 System.out.println( "put file " + request.getPathInfo() );
1046 putCallNumber++;
1047 response.setStatus( HttpServletResponse.SC_CREATED );
1048 }
1049 }
1050
1051 private static class AuthorizingProxyHandler
1052 extends TestHeaderHandler
1053 {
1054
1055 public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch )
1056 throws IOException, ServletException
1057 {
1058 System.out.println( " handle proxy request" );
1059 if ( request.getHeader( "Proxy-Authorization" ) == null )
1060 {
1061 response.setStatus( 407 );
1062 response.addHeader( "Proxy-Authenticate", "Basic realm=\"Squid proxy-caching web server\"" );
1063
1064 ( (Request) request ).setHandled( true );
1065 return;
1066 }
1067 super.handle( target, request, response, dispatch );
1068 }
1069 }
1070
1071 private static class TestHeaderHandler
1072 extends AbstractHandler
1073 {
1074 private Map headers = Collections.EMPTY_MAP;
1075
1076 public TestHeaderHandler()
1077 {
1078 }
1079
1080 public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch )
1081 throws IOException, ServletException
1082 {
1083 headers = new HashMap();
1084 for ( Enumeration e = request.getHeaderNames(); e.hasMoreElements(); )
1085 {
1086 String name = (String) e.nextElement();
1087 headers.put( name, request.getHeader( name ) );
1088 }
1089
1090 response.setContentType( "text/plain" );
1091 response.setStatus( HttpServletResponse.SC_OK );
1092 response.getWriter().println( "Hello, World!" );
1093
1094 ( (Request) request ).setHandled( true );
1095 }
1096
1097 }
1098
1099 protected TestSecurityHandler createSecurityHandler()
1100 {
1101 Constraint constraint = new Constraint();
1102 constraint.setName( Constraint.__BASIC_AUTH );
1103 constraint.setRoles( new String[]{ "admin" } );
1104 constraint.setAuthenticate( true );
1105
1106 ConstraintMapping cm = new ConstraintMapping();
1107 cm.setConstraint( constraint );
1108 cm.setPathSpec( "/*" );
1109
1110 TestSecurityHandler sh = new TestSecurityHandler();
1111 HashUserRealm hashUserRealm = new HashUserRealm( "MyRealm" );
1112 hashUserRealm.put( "user", "secret" );
1113 hashUserRealm.addUserToRole( "user", "admin" );
1114 sh.setUserRealm( hashUserRealm );
1115 sh.setConstraintMappings( new ConstraintMapping[]{ cm } );
1116 return sh;
1117 }
1118
1119 public static class TestSecurityHandler
1120 extends SecurityHandler
1121 {
1122
1123 public List<SecurityHandlerRequestReponse> securityHandlerRequestReponses =
1124 new ArrayList<SecurityHandlerRequestReponse>();
1125
1126 @Override
1127 public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch )
1128 throws IOException, ServletException
1129 {
1130 String method = request.getMethod();
1131 super.handle( target, request, response, dispatch );
1132 System.out.println( "method in SecurityHandler: " + method );
1133
1134 securityHandlerRequestReponses.add(
1135 new SecurityHandlerRequestReponse( method, ( (Response) response ).getStatus() ) );
1136 }
1137
1138 }
1139
1140 public static class SecurityHandlerRequestReponse
1141 {
1142 public String method;
1143
1144 public int responseCode;
1145
1146 private SecurityHandlerRequestReponse( String method, int responseCode )
1147 {
1148 this.method = method;
1149 this.responseCode = responseCode;
1150 }
1151
1152 @Override
1153 public String toString()
1154 {
1155 final StringBuilder sb = new StringBuilder();
1156 sb.append( "SecurityHandlerRequestReponse" );
1157 sb.append( "{method='" ).append( method ).append( '\'' );
1158 sb.append( ", responseCode=" ).append( responseCode );
1159 sb.append( '}' );
1160 return sb.toString();
1161 }
1162 }
1163 }