View Javadoc
1   package org.apache.maven.wagon.http;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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          // File round trip testing
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      * test set of User-Agent as it's done by aether wagon connector with using setHttpHeaders
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                 //we don't care about lightweight
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         // protocol is wagon protocol but in fact dav is http(s)
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         // protocol is wagon protocol but in fact dav is http(s)
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         // protocol is wagon protocol but in fact dav is http(s)
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         // protocol is wagon protocol but in fact dav is http(s)
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         // what an UGLY hack!
1082         // but apparently jetty needs some time to free up resources
1083         // <5s: broken test :(
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         // what an UGLY hack!
1138         // but apparently jetty needs some time to free up resources
1139         // <5s: broken test :(
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             // write out different data than non-gz file, so we can
1452             // assert the gz version was returned
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         // ensure we didn't use chunked transfer which doesn't work on ngnix
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             // no op
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 }