1 package org.apache.maven.wagon.http;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.OutputStream;
26 import java.net.URLDecoder;
27 import java.util.Enumeration;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.Properties;
31 import java.util.zip.GZIPOutputStream;
32
33 import javax.servlet.ServletException;
34 import javax.servlet.ServletInputStream;
35 import javax.servlet.http.HttpServletRequest;
36 import javax.servlet.http.HttpServletResponse;
37
38 import org.apache.maven.wagon.ConnectionException;
39 import org.apache.maven.wagon.FileTestUtils;
40 import org.apache.maven.wagon.ResourceDoesNotExistException;
41 import org.apache.maven.wagon.StreamingWagon;
42 import org.apache.maven.wagon.StreamingWagonTestCase;
43 import org.apache.maven.wagon.TransferFailedException;
44 import org.apache.maven.wagon.Wagon;
45 import org.apache.maven.wagon.authentication.AuthenticationException;
46 import org.apache.maven.wagon.authentication.AuthenticationInfo;
47 import org.apache.maven.wagon.authorization.AuthorizationException;
48 import org.apache.maven.wagon.proxy.ProxyInfo;
49 import org.apache.maven.wagon.repository.Repository;
50 import org.apache.maven.wagon.resource.Resource;
51 import org.codehaus.plexus.util.FileUtils;
52 import org.codehaus.plexus.util.IOUtil;
53 import org.codehaus.plexus.util.StringOutputStream;
54 import org.mortbay.jetty.Handler;
55 import org.mortbay.jetty.HttpConnection;
56 import org.mortbay.jetty.Request;
57 import org.mortbay.jetty.Server;
58 import org.mortbay.jetty.handler.AbstractHandler;
59 import org.mortbay.jetty.handler.HandlerCollection;
60 import org.mortbay.jetty.security.Constraint;
61 import org.mortbay.jetty.security.ConstraintMapping;
62 import org.mortbay.jetty.security.HashUserRealm;
63 import org.mortbay.jetty.security.SecurityHandler;
64 import org.mortbay.jetty.servlet.Context;
65 import org.mortbay.jetty.servlet.DefaultServlet;
66 import org.mortbay.jetty.servlet.ServletHolder;
67
68
69
70
71 public abstract class HttpWagonTestCase
72 extends StreamingWagonTestCase
73 {
74 private Server server;
75
76 protected void setupWagonTestingFixtures()
77 throws Exception
78 {
79
80
81 File file = FileTestUtils.createUniqueFile( "local-repository", "test-resource" );
82
83 file.delete();
84
85 file.getParentFile().mkdirs();
86
87 File repositoryDirectory = getRepositoryDirectory();
88 FileUtils.deleteDirectory( repositoryDirectory );
89 repositoryDirectory.mkdirs();
90
91 server = new Server( 10007 );
92
93 PutHandler putHandler = new PutHandler( repositoryDirectory );
94 server.addHandler( putHandler );
95
96 createContext( server, repositoryDirectory );
97
98 addConnectors( server );
99
100 server.start();
101 }
102
103 protected void createContext( Server server, File repositoryDirectory )
104 throws IOException
105 {
106 Context root = new Context( server, "/", Context.SESSIONS );
107 root.setResourceBase( repositoryDirectory.getAbsolutePath() );
108 ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
109 root.addServlet( servletHolder, "/*" );
110 }
111
112 protected void tearDownWagonTestingFixtures()
113 throws Exception
114 {
115 server.stop();
116 }
117
118 public void testWagonGetFileList()
119 throws Exception
120 {
121 File dir = getRepositoryDirectory();
122 FileUtils.deleteDirectory( dir );
123
124 File f = new File( dir, "file-list" );
125 f.mkdirs();
126
127 super.testWagonGetFileList();
128 }
129
130 public void testHttpHeaders()
131 throws Exception
132 {
133 Properties properties = new Properties();
134 properties.setProperty( "User-Agent", "Maven-Wagon/1.0" );
135
136 StreamingWagon wagon = (StreamingWagon) getWagon();
137
138 setHttpHeaders( wagon, properties );
139
140 Server server = new Server( 0 );
141 TestHeaderHandler handler = new TestHeaderHandler();
142 server.setHandler( handler );
143 addConnectors( server );
144 server.start();
145
146 wagon.connect( new Repository( "id", getProtocol() + "://localhost:" + server.getConnectors()[0].getLocalPort() ) );
147
148 wagon.getToStream( "resource", new StringOutputStream() );
149
150 wagon.disconnect();
151
152 server.stop();
153
154 assertEquals( "Maven-Wagon/1.0", handler.headers.get( "User-Agent" ) );
155 }
156
157 protected abstract void setHttpHeaders( StreamingWagon wagon, Properties properties );
158
159 protected void addConnectors( Server server )
160 {
161 }
162
163 protected String getRepositoryUrl( Server server )
164 {
165 int localPort = server.getConnectors()[0].getLocalPort();
166 return getProtocol() + "://localhost:" + localPort;
167 }
168
169 public void testGetForbidden()
170 throws Exception
171 {
172 try
173 {
174 runTestGet( HttpServletResponse.SC_FORBIDDEN );
175 fail();
176 }
177 catch ( AuthorizationException e )
178 {
179 assertTrue( true );
180 }
181 }
182
183 public void testGet404()
184 throws Exception
185 {
186 try
187 {
188 runTestGet( HttpServletResponse.SC_NOT_FOUND );
189 fail();
190 }
191 catch ( ResourceDoesNotExistException e )
192 {
193 assertTrue( true );
194 }
195 }
196
197 public void testGet500()
198 throws Exception
199 {
200 try
201 {
202 runTestGet( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
203 fail();
204 }
205 catch ( TransferFailedException e )
206 {
207 assertTrue( true );
208 }
209 }
210
211 private void runTestGet( int status )
212 throws Exception, ConnectionException, AuthenticationException, TransferFailedException,
213 ResourceDoesNotExistException, AuthorizationException
214 {
215 StreamingWagon wagon = (StreamingWagon) getWagon();
216
217 Server server = new Server( 0 );
218 StatusHandler handler = new StatusHandler();
219 handler.setStatusToReturn( status );
220 server.setHandler( handler );
221 addConnectors( server );
222 server.start();
223
224 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) );
225
226 try
227 {
228 wagon.getToStream( "resource", new StringOutputStream() );
229 fail();
230 }
231 finally
232 {
233 wagon.disconnect();
234
235 server.stop();
236 }
237 }
238
239 public void testResourceExistsForbidden()
240 throws Exception
241 {
242 try
243 {
244 runTestResourceExists( HttpServletResponse.SC_FORBIDDEN );
245 fail();
246 }
247 catch ( AuthorizationException e )
248 {
249 assertTrue( true );
250 }
251 }
252
253 public void testResourceExists404()
254 throws Exception
255 {
256 try
257 {
258 assertFalse( runTestResourceExists( HttpServletResponse.SC_NOT_FOUND ) );
259 }
260 catch ( ResourceDoesNotExistException e )
261 {
262 assertTrue( true );
263 }
264 }
265
266 public void testResourceExists500()
267 throws Exception
268 {
269 try
270 {
271 runTestResourceExists( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
272 fail();
273 }
274 catch ( TransferFailedException e )
275 {
276 assertTrue( true );
277 }
278 }
279
280 private boolean runTestResourceExists( int status )
281 throws Exception, ConnectionException, AuthenticationException, TransferFailedException,
282 ResourceDoesNotExistException, AuthorizationException
283 {
284 StreamingWagon wagon = (StreamingWagon) getWagon();
285
286 Server server = new Server( 0 );
287 StatusHandler handler = new StatusHandler();
288 handler.setStatusToReturn( status );
289 server.setHandler( handler );
290 addConnectors( server );
291 server.start();
292
293 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) );
294
295 try
296 {
297 return wagon.resourceExists( "resource" );
298 }
299 finally
300 {
301 wagon.disconnect();
302
303 server.stop();
304 }
305 }
306
307 protected long getExpectedLastModifiedOnGet( Repository repository, Resource resource )
308 {
309 File file = new File( getRepositoryDirectory(), resource.getName() );
310 return ( file.lastModified() / 1000 ) * 1000;
311 }
312
313 protected File getRepositoryDirectory()
314 {
315 return getTestFile( "target/test-output/http-repository" );
316 }
317
318 public void testGzipGet()
319 throws Exception
320 {
321 Server server = new Server( 10008 );
322
323 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
324 Context root = new Context( server, "/", Context.SESSIONS );
325 root.setResourceBase( localRepositoryPath );
326 ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
327 servletHolder.setInitParameter( "gzip", "true" );
328 root.addServlet( servletHolder, "/*" );
329 addConnectors( server );
330 server.start();
331
332 try
333 {
334 Wagon wagon = getWagon();
335
336 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) );
337
338 File sourceFile = new File( localRepositoryPath + "/gzip" );
339
340 sourceFile.deleteOnExit();
341
342 String resName = "gzip-res.txt";
343 String sourceContent = writeTestFileGzip( sourceFile, resName );
344
345 wagon.connect( testRepository );
346
347 File destFile = FileTestUtils.createUniqueFile( getName(), getName() );
348
349 destFile.deleteOnExit();
350
351 wagon.get( "gzip/" + resName, destFile );
352
353 wagon.disconnect();
354
355 String destContent = FileUtils.fileRead( destFile );
356
357 assertEquals( sourceContent, destContent );
358 }
359 finally
360 {
361 server.stop();
362 }
363 }
364
365 public void testProxiedRequest()
366 throws Exception
367 {
368 ProxyInfo proxyInfo = createProxyInfo();
369 TestHeaderHandler handler = new TestHeaderHandler();
370
371 runTestProxiedRequest( proxyInfo, handler );
372 }
373
374 public void testProxiedRequestWithAuthentication()
375 throws Exception
376 {
377 ProxyInfo proxyInfo = createProxyInfo();
378 proxyInfo.setUserName( "user" );
379 proxyInfo.setPassword( "secret" );
380 TestHeaderHandler handler = new AuthorizingProxyHandler();
381
382 runTestProxiedRequest( proxyInfo, handler );
383
384 assertTrue( handler.headers.containsKey( "Proxy-Authorization" ) );
385 }
386
387 private void runTestProxiedRequest( ProxyInfo proxyInfo, TestHeaderHandler handler )
388 throws Exception, IOException, ConnectionException, AuthenticationException, ResourceDoesNotExistException,
389 TransferFailedException, AuthorizationException
390 {
391 Server proxyServer = new Server( 10007 );
392
393 proxyServer.setHandler( handler );
394 proxyServer.start();
395
396 proxyInfo.setPort( 10007 );
397
398 try
399 {
400 StreamingWagon wagon = (StreamingWagon) getWagon();
401
402 Repository testRepository = new Repository( "id", "http://www.example.com/" );
403
404 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
405 File sourceFile = new File( localRepositoryPath, "test-proxied-resource" );
406 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "content" );
407
408 wagon.connect( testRepository, proxyInfo );
409
410 StringOutputStream out = new StringOutputStream();
411 try
412 {
413 wagon.getToStream( "test-proxied-resource", out );
414
415 assertTrue( handler.headers.containsKey( "Proxy-Connection" ) );
416 }
417 finally
418 {
419 wagon.disconnect();
420 }
421 }
422 finally
423 {
424 proxyServer.stop();
425 }
426 }
427
428 private ProxyInfo createProxyInfo()
429 {
430 ProxyInfo proxyInfo = new ProxyInfo();
431 proxyInfo.setHost( "localhost" );
432 proxyInfo.setNonProxyHosts( null );
433 proxyInfo.setType( "http" );
434 return proxyInfo;
435 }
436
437 public void testSecuredGetUnauthorized()
438 throws Exception
439 {
440 try
441 {
442 runTestSecuredGet( null );
443 fail();
444 }
445 catch ( AuthorizationException e )
446 {
447 assertTrue( true );
448 }
449 }
450
451 public void testSecuredGetWrongPassword()
452 throws Exception
453 {
454 try
455 {
456 AuthenticationInfo authInfo = new AuthenticationInfo();
457 authInfo.setUserName( "user" );
458 authInfo.setPassword( "admin" );
459 runTestSecuredGet( authInfo );
460 fail();
461 }
462 catch ( AuthorizationException e )
463 {
464 assertTrue( true );
465 }
466 }
467
468 public void testSecuredGet()
469 throws Exception
470 {
471 AuthenticationInfo authInfo = new AuthenticationInfo();
472 authInfo.setUserName( "user" );
473 authInfo.setPassword( "secret" );
474 runTestSecuredGet( authInfo );
475 }
476
477 public void runTestSecuredGet( AuthenticationInfo authInfo )
478 throws Exception
479 {
480 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
481 Server server = createSecurityServer( localRepositoryPath );
482 server.start();
483
484 try
485 {
486 StreamingWagon wagon = (StreamingWagon) getWagon();
487
488 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) );
489
490 File sourceFile = new File( localRepositoryPath, "test-secured-resource" );
491 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "top secret" );
492
493 wagon.connect( testRepository, authInfo );
494
495 StringOutputStream out = new StringOutputStream();
496 try
497 {
498 wagon.getToStream( "test-secured-resource", out );
499 }
500 finally
501 {
502 wagon.disconnect();
503 }
504
505 assertEquals( "top secret", out.toString() );
506 }
507 finally
508 {
509 server.stop();
510 }
511 }
512
513 public void testSecuredResourceExistsUnauthorized()
514 throws Exception
515 {
516 try
517 {
518 runTestSecuredResourceExists( null );
519 fail();
520 }
521 catch ( AuthorizationException e )
522 {
523 assertTrue( true );
524 }
525 }
526
527 public void testSecuredResourceExistsWrongPassword()
528 throws Exception
529 {
530 try
531 {
532 AuthenticationInfo authInfo = new AuthenticationInfo();
533 authInfo.setUserName( "user" );
534 authInfo.setPassword( "admin" );
535 runTestSecuredResourceExists( authInfo );
536 }
537 catch ( AuthorizationException e )
538 {
539 assertTrue( true );
540 }
541 }
542
543 public void testSecuredResourceExists()
544 throws Exception
545 {
546 AuthenticationInfo authInfo = new AuthenticationInfo();
547 authInfo.setUserName( "user" );
548 authInfo.setPassword( "secret" );
549 runTestSecuredResourceExists( authInfo );
550 }
551
552 public void runTestSecuredResourceExists( AuthenticationInfo authInfo )
553 throws Exception
554 {
555 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
556 Server server = createSecurityServer( localRepositoryPath );
557 server.start();
558
559 try
560 {
561 StreamingWagon wagon = (StreamingWagon) getWagon();
562
563 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) );
564
565 File sourceFile = new File( localRepositoryPath, "test-secured-resource-exists" );
566 FileUtils.fileWrite( sourceFile.getAbsolutePath(), "top secret" );
567
568 wagon.connect( testRepository, authInfo );
569
570 try
571 {
572 assertTrue( wagon.resourceExists( "test-secured-resource-exists" ) );
573
574 assertFalse( wagon.resourceExists( "test-secured-resource-not-exists" ) );
575 }
576 finally
577 {
578 wagon.disconnect();
579 }
580 }
581 finally
582 {
583 server.stop();
584 }
585 }
586
587 private Server createSecurityServer( String localRepositoryPath )
588 {
589 Server server = new Server( 0 );
590
591 SecurityHandler sh = createSecurityHandler();
592
593 Context root = new Context( Context.SESSIONS );
594 root.setContextPath( "/" );
595 root.addHandler( sh );
596 root.setResourceBase( localRepositoryPath );
597 ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
598 root.addServlet( servletHolder, "/*" );
599
600 server.setHandler( root );
601 addConnectors( server );
602 return server;
603 }
604
605 protected SecurityHandler createSecurityHandler()
606 {
607 Constraint constraint = new Constraint();
608 constraint.setName( Constraint.__BASIC_AUTH );
609 constraint.setRoles( new String[] { "admin" } );
610 constraint.setAuthenticate( true );
611
612 ConstraintMapping cm = new ConstraintMapping();
613 cm.setConstraint( constraint );
614 cm.setPathSpec( "/*" );
615
616 SecurityHandler sh = new SecurityHandler();
617 HashUserRealm hashUserRealm = new HashUserRealm( "MyRealm" );
618 hashUserRealm.put( "user", "secret" );
619 hashUserRealm.addUserToRole( "user", "admin" );
620 sh.setUserRealm( hashUserRealm );
621 sh.setConstraintMappings( new ConstraintMapping[] { cm } );
622 return sh;
623 }
624
625 private String writeTestFileGzip( File parent, String child )
626 throws IOException
627 {
628 File file = new File( parent, child );
629 file.getParentFile().mkdirs();
630 file.deleteOnExit();
631 OutputStream out = new FileOutputStream( file );
632 out.write( child.getBytes() );
633 out.close();
634
635 file = new File( parent, child + ".gz" );
636 file.deleteOnExit();
637 out = new FileOutputStream( file );
638 out = new GZIPOutputStream( out );
639
640
641 String content = file.getAbsolutePath();
642 out.write( content.getBytes() );
643 out.close();
644 return content;
645 }
646
647 public void testPutForbidden()
648 throws Exception
649 {
650 try
651 {
652 runTestPut( HttpServletResponse.SC_FORBIDDEN );
653 fail();
654 }
655 catch ( AuthorizationException e )
656 {
657 assertTrue( true );
658 }
659 }
660
661 public void testPut404()
662 throws Exception
663 {
664 try
665 {
666 runTestPut( HttpServletResponse.SC_NOT_FOUND );
667 fail();
668 }
669 catch ( ResourceDoesNotExistException e )
670 {
671 assertTrue( true );
672 }
673 }
674
675 public void testPut500()
676 throws Exception
677 {
678 try
679 {
680 runTestPut( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
681 fail();
682 }
683 catch ( TransferFailedException e )
684 {
685 assertTrue( true );
686 }
687 }
688
689 private void runTestPut( int status )
690 throws Exception, ConnectionException, AuthenticationException, TransferFailedException,
691 ResourceDoesNotExistException, AuthorizationException
692 {
693 StreamingWagon wagon = (StreamingWagon) getWagon();
694
695 Server server = new Server( 0 );
696 StatusHandler handler = new StatusHandler();
697 handler.setStatusToReturn( status );
698 server.setHandler( handler );
699 addConnectors( server );
700 server.start();
701
702 wagon.connect( new Repository( "id", getRepositoryUrl( server ) ) );
703
704 File tempFile = File.createTempFile( "wagon", "tmp" );
705 tempFile.deleteOnExit();
706 FileUtils.fileWrite( tempFile.getAbsolutePath(), "content" );
707
708 try
709 {
710 wagon.put( tempFile, "resource" );
711 fail();
712 }
713 finally
714 {
715 wagon.disconnect();
716
717 server.stop();
718
719 tempFile.delete();
720 }
721 }
722
723 public void testSecuredPutUnauthorized()
724 throws Exception
725 {
726 try
727 {
728 runTestSecuredPut( null );
729 fail();
730 }
731 catch ( TransferFailedException e )
732 {
733 assertTrue( true );
734 }
735 }
736
737 public void testSecuredPutWrongPassword()
738 throws Exception
739 {
740 try
741 {
742 AuthenticationInfo authInfo = new AuthenticationInfo();
743 authInfo.setUserName( "user" );
744 authInfo.setPassword( "admin" );
745 runTestSecuredPut( authInfo );
746 fail();
747 }
748 catch ( TransferFailedException e )
749 {
750 assertTrue( true );
751 }
752 }
753
754 public void testSecuredPut()
755 throws Exception
756 {
757 AuthenticationInfo authInfo = new AuthenticationInfo();
758 authInfo.setUserName( "user" );
759 authInfo.setPassword( "secret" );
760 runTestSecuredPut( authInfo );
761 }
762
763 public void runTestSecuredPut( AuthenticationInfo authInfo )
764 throws Exception
765 {
766 String localRepositoryPath = FileTestUtils.getTestOutputDir().toString();
767 Server server = new Server( 0 );
768
769 SecurityHandler sh = createSecurityHandler();
770
771 PutHandler handler = new PutHandler( new File( localRepositoryPath ) );
772
773 HandlerCollection handlers = new HandlerCollection();
774 handlers.setHandlers( new Handler[] { sh, handler } );
775
776 server.setHandler( handlers );
777 addConnectors( server );
778 server.start();
779
780 try
781 {
782 StreamingWagon wagon = (StreamingWagon) getWagon();
783
784 Repository testRepository = new Repository( "id", getRepositoryUrl( server ) );
785
786 wagon.connect( testRepository, authInfo );
787
788 File sourceFile = new File( localRepositoryPath, "test-secured-put-resource" );
789 sourceFile.delete();
790 assertFalse( sourceFile.exists() );
791
792 File tempFile = File.createTempFile( "wagon", "tmp" );
793 tempFile.deleteOnExit();
794 FileUtils.fileWrite( tempFile.getAbsolutePath(), "put top secret" );
795
796 try
797 {
798 wagon.put( tempFile, "test-secured-put-resource" );
799 }
800 finally
801 {
802 wagon.disconnect();
803 tempFile.delete();
804 }
805
806 assertEquals( "put top secret", FileUtils.fileRead( sourceFile.getAbsolutePath() ) );
807 }
808 finally
809 {
810 server.stop();
811 }
812 }
813
814 static class StatusHandler
815 extends AbstractHandler
816 {
817 private int status;
818
819 public void setStatusToReturn( int status )
820 {
821 this.status = status;
822 }
823
824 public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch )
825 throws IOException, ServletException
826 {
827 if ( status != 0 )
828 {
829 response.setStatus( status );
830 ( (Request) request ).setHandled( true );
831 }
832 }
833 }
834
835 static class PutHandler
836 extends AbstractHandler
837 {
838 private final File resourceBase;
839
840 public PutHandler( File repositoryDirectory )
841 {
842 this.resourceBase = repositoryDirectory;
843 }
844
845 public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch )
846 throws IOException, ServletException
847 {
848 Request base_request =
849 request instanceof Request ? (Request) request : HttpConnection.getCurrentConnection().getRequest();
850
851 if ( base_request.isHandled() || !"PUT".equals( base_request.getMethod() ) )
852 {
853 return;
854 }
855
856 base_request.setHandled( true );
857
858 File file = new File( resourceBase, URLDecoder.decode( request.getPathInfo() ) );
859 file.getParentFile().mkdirs();
860 FileOutputStream out = new FileOutputStream( file );
861 ServletInputStream in = request.getInputStream();
862 try
863 {
864 IOUtil.copy( in, out );
865 }
866 finally
867 {
868 in.close();
869 out.close();
870 }
871
872 response.setStatus( HttpServletResponse.SC_CREATED );
873 }
874 }
875
876 private static class AuthorizingProxyHandler
877 extends TestHeaderHandler
878 {
879 public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch )
880 throws IOException, ServletException
881 {
882 if ( request.getHeader( "Proxy-Authorization" ) == null )
883 {
884 response.setStatus( 407 );
885 response.addHeader( "Proxy-Authenticate", "Basic realm=\"Squid proxy-caching web server\"" );
886
887 ( (Request) request ).setHandled( true );
888 return;
889 }
890 super.handle( target, request, response, dispatch );
891 }
892 }
893
894 private static class TestHeaderHandler
895 extends AbstractHandler
896 {
897 private Map headers;
898
899 public TestHeaderHandler()
900 {
901 }
902
903 public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch )
904 throws IOException, ServletException
905 {
906 headers = new HashMap();
907 for ( Enumeration e = request.getHeaderNames(); e.hasMoreElements(); )
908 {
909 String name = (String) e.nextElement();
910 headers.put( name, request.getHeader( name ) );
911 }
912
913 response.setContentType( "text/plain" );
914 response.setStatus( HttpServletResponse.SC_OK );
915 response.getWriter().println( "Hello, World!" );
916
917 ( (Request) request ).setHandled( true );
918 }
919
920 }
921 }