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