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