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