001package org.apache.maven.wagon.providers.webdav; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import it.could.webdav.DAVServlet; 023import org.apache.http.HttpException; 024import org.apache.http.client.methods.CloseableHttpResponse; 025import org.apache.http.client.methods.HttpUriRequest; 026import org.apache.maven.wagon.ResourceDoesNotExistException; 027import org.apache.maven.wagon.StreamingWagon; 028import org.apache.maven.wagon.TransferFailedException; 029import org.apache.maven.wagon.Wagon; 030import org.apache.maven.wagon.http.HttpWagonTestCase; 031import org.apache.maven.wagon.repository.Repository; 032import org.apache.maven.wagon.resource.Resource; 033import org.apache.maven.wagon.shared.http.HttpConfiguration; 034import org.apache.maven.wagon.shared.http.HttpMethodConfiguration; 035import org.eclipse.jetty.server.Server; 036import org.eclipse.jetty.servlet.ServletContextHandler; 037import org.eclipse.jetty.servlet.ServletHolder; 038 039import java.io.File; 040import java.io.IOException; 041import java.net.SocketTimeoutException; 042import java.util.List; 043import java.util.Properties; 044 045import javax.servlet.http.HttpServletResponse; 046 047/* 048 * WebDAV Wagon Test 049 * 050 * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a> 051 * 052 * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a> 053 */ 054public class WebDavWagonTest 055 extends HttpWagonTestCase 056{ 057 058 protected String getTestRepositoryUrl() 059 throws IOException 060 { 061 return getProtocol() + "://localhost:" + getTestRepositoryPort() + "/newfolder/folder2/"; 062 } 063 064 protected String getProtocol() 065 { 066 return "dav"; 067 } 068 069 protected ServletContextHandler createContext( Server server, File repositoryDirectory ) 070 throws IOException 071 { 072 ServletContextHandler dav = new ServletContextHandler( ServletContextHandler.SESSIONS ); 073 ServletHolder davServletHolder = new ServletHolder( new DAVServlet() ); 074 davServletHolder.setInitParameter( "rootPath", repositoryDirectory.getAbsolutePath() ); 075 davServletHolder.setInitParameter( "xmlOnly", "false" ); 076 dav.addServlet( davServletHolder, "/*" ); 077 return dav; 078 } 079 080 protected long getExpectedLastModifiedOnGet( Repository repository, Resource resource ) 081 { 082 File file = new File( getDavRepository(), resource.getName() ); 083 return ( file.lastModified() / 1000L ) * 1000L; 084 } 085 086 087 private File getDavRepository() 088 { 089 return getTestFile( "target/test-output/http-repository/newfolder/folder2" ); 090 } 091 092 private void assertURL( String userUrl, String expectedUrl ) 093 { 094 Repository repo = new Repository( "test-geturl", userUrl ); 095 String actualUrl = ( new WebDavWagon() ).getURL( repo ); 096 assertEquals( "WebDavWagon.getURL(" + userUrl + ")", expectedUrl, actualUrl ); 097 } 098 099 /** 100 * Tests the maven 2.0.x way to define a webdav URL without SSL. 101 */ 102 public void testGetURLDavHttp() 103 { 104 assertURL( "dav:http://localhost:9080/dav/", 105 "http://localhost:9080/dav/" ); 106 } 107 108 /** 109 * Tests the maven 2.0.x way to define a webdav URL with SSL. 110 */ 111 public void testGetURLDavHttps() 112 { 113 assertURL( "dav:https://localhost:9443/dav/", 114 "https://localhost:9443/dav/" ); 115 } 116 117 /** 118 * Tests the URI spec way of defining a webdav URL without SSL. 119 */ 120 public void testGetURLDavUri() 121 { 122 assertURL( "dav://localhost:9080/dav/", 123 "http://localhost:9080/dav/" ); 124 } 125 126 /** 127 * Tests the URI spec way of defining a webdav URL with SSL. 128 */ 129 public void testGetURLDavUriWithSsl() 130 { 131 assertURL( "davs://localhost:9443/dav/", 132 "https://localhost:9443/dav/" ); 133 } 134 135 /** 136 * Tests the URI spec way of defining a webdav URL without SSL. 137 */ 138 public void testGetURLDavPlusHttp() 139 { 140 assertURL( "dav+https://localhost:" + getTestRepositoryPort() + "/dav/", 141 "https://localhost:" + getTestRepositoryPort() + "/dav/" ); 142 } 143 144 /** 145 * Tests the URI spec way of defining a webdav URL with SSL. 146 */ 147 public void testGetURLDavPlusHttps() 148 { 149 assertURL( "dav+https://localhost:9443/dav/", 150 "https://localhost:9443/dav/" ); 151 } 152 153 public void testMkdirs() 154 throws Exception 155 { 156 setupWagonTestingFixtures(); 157 158 setupRepositories(); 159 160 WebDavWagon wagon = (WebDavWagon) getWagon(); 161 wagon.connect( testRepository, getAuthInfo() ); 162 163 try 164 { 165 File dir = getRepositoryDirectory(); 166 167 // check basedir also doesn't exist and will need to be created 168 dir = new File( dir, testRepository.getBasedir() ); 169 assertFalse( dir.exists() ); 170 171 // test leading / 172 assertFalse( new File( dir, "foo" ).exists() ); 173 wagon.mkdirs( "/foo" ); 174 assertTrue( new File( dir, "foo" ).exists() ); 175 176 // test trailing / 177 assertFalse( new File( dir, "bar" ).exists() ); 178 wagon.mkdirs( "bar/" ); 179 assertTrue( new File( dir, "bar" ).exists() ); 180 181 // test when already exists 182 wagon.mkdirs( "bar" ); 183 184 // test several parts 185 assertFalse( new File( dir, "1/2/3/4" ).exists() ); 186 wagon.mkdirs( "1/2/3/4" ); 187 assertTrue( new File( dir, "1/2/3/4" ).exists() ); 188 189 // test additional part and trailing / 190 assertFalse( new File( dir, "1/2/3/4/5" ).exists() ); 191 wagon.mkdirs( "1/2/3/4/5/" ); 192 assertTrue( new File( dir, "1/2/3/4" ).exists() ); 193 } 194 finally 195 { 196 wagon.disconnect(); 197 198 tearDownWagonTestingFixtures(); 199 } 200 } 201 202 public void testMkdirsWithNoBasedir() 203 throws Exception 204 { 205 // WAGON-244 206 setupWagonTestingFixtures(); 207 208 setupRepositories(); 209 210 // reconstruct with no basedir 211 testRepository.setUrl( 212 testRepository.getProtocol() + "://" + testRepository.getHost() + ":" + testRepository.getPort() ); 213 214 WebDavWagon wagon = (WebDavWagon) getWagon(); 215 wagon.connect( testRepository, getAuthInfo() ); 216 217 try 218 { 219 File dir = getRepositoryDirectory(); 220 221 // check basedir also doesn't exist and will need to be created 222 dir = new File( dir, testRepository.getBasedir() ); 223 assertTrue( dir.exists() ); 224 225 // test leading / 226 assertFalse( new File( dir, "foo" ).exists() ); 227 wagon.mkdirs( "/foo" ); 228 assertTrue( new File( dir, "foo" ).exists() ); 229 } 230 finally 231 { 232 wagon.disconnect(); 233 234 tearDownWagonTestingFixtures(); 235 } 236 } 237 238 protected void setHttpConfiguration( StreamingWagon wagon, Properties headers, Properties params ) 239 { 240 HttpConfiguration config = new HttpConfiguration(); 241 242 HttpMethodConfiguration methodConfiguration = new HttpMethodConfiguration(); 243 methodConfiguration.setHeaders( headers ); 244 methodConfiguration.setParams( params ); 245 config.setAll( methodConfiguration ); 246 ( (WebDavWagon) wagon ).setHttpConfiguration( config ); 247 } 248 249 /** 250 * Make sure Wagon WebDAV can detect remote directory 251 * 252 * @throws Exception 253 */ 254 public void testWagonWebDavGetFileList() 255 throws Exception 256 { 257 setupWagonTestingFixtures(); 258 259 setupRepositories(); 260 261 String dirName = "file-list"; 262 263 String filenames[] = 264 new String[]{ "test-resource.txt", "test-resource.pom", "test-resource b.txt", "more-resources.dat" }; 265 266 for ( int i = 0; i < filenames.length; i++ ) 267 { 268 putFile( dirName + "/" + filenames[i], dirName + "/" + filenames[i], filenames[i] + "\n" ); 269 } 270 271 String dirnames[] = new String[]{ "test-dir1", "test-dir2" }; 272 273 for ( int i = 0; i < dirnames.length; i++ ) 274 { 275 new File( getDavRepository(), dirName + "/" + dirnames[i] ).mkdirs(); 276 } 277 278 Wagon wagon = getWagon(); 279 280 wagon.connect( testRepository, getAuthInfo() ); 281 282 List<String> list = wagon.getFileList( dirName ); 283 284 assertNotNull( "file list should not be null.", list ); 285 assertEquals( "file list should contain 6 items", 6, list.size() ); 286 287 for ( int i = 0; i < filenames.length; i++ ) 288 { 289 assertTrue( "Filename '" + filenames[i] + "' should be in list.", list.contains( filenames[i] ) ); 290 } 291 292 for ( int i = 0; i < dirnames.length; i++ ) 293 { 294 assertTrue( "Directory '" + dirnames[i] + "' should be in list.", list.contains( dirnames[i] + "/" ) ); 295 } 296 297 /////////////////////////////////////////////////////////////////////////// 298 list = wagon.getFileList( "" ); 299 assertNotNull( "file list should not be null.", list ); 300 assertEquals( "file list should contain 1 items", 1, list.size() ); 301 302 /////////////////////////////////////////////////////////////////////////// 303 list = wagon.getFileList( dirName + "/test-dir1" ); 304 assertNotNull( "file list should not be null.", list ); 305 assertEquals( "file list should contain 0 items", 0, list.size() ); 306 307 ///////////////////////////////////////////////////////////////////////////// 308 try 309 { 310 list = wagon.getFileList( dirName + "/test-dir-bogus" ); 311 fail( "Exception expected" ); 312 } 313 catch ( ResourceDoesNotExistException e ) 314 { 315 316 } 317 318 wagon.disconnect(); 319 320 tearDownWagonTestingFixtures(); 321 } 322 323 324 public void testWagonFailsOnPutFailureByDefault() 325 throws Exception 326 { 327 setupWagonTestingFixtures(); 328 329 setupRepositories(); 330 331 File testFile = getTempFile(); 332 333 System.clearProperty( WebDavWagon.CONTINUE_ON_FAILURE_PROPERTY ); 334 335 WebDavWagon wagon = new TimeoutSimulatingWagon(); 336 wagon.connect( testRepository, getAuthInfo() ); 337 338 try 339 { 340 String filename = TimeoutSimulatingWagon.TIMEOUT_TRIGGER + ".txt"; 341 342 try 343 { 344 wagon.put( testFile, filename ); 345 fail( "Exception expected" ); 346 } 347 catch ( TransferFailedException e ) 348 { 349 350 } 351 } 352 finally 353 { 354 wagon.disconnect(); 355 356 tearDownWagonTestingFixtures(); 357 } 358 } 359 360 private File getTempFile() 361 throws IOException 362 { 363 File inputFile = File.createTempFile( "test-resource", ".txt" ); 364 inputFile.deleteOnExit(); 365 return inputFile; 366 } 367 368 private static class TimeoutSimulatingWagon 369 extends WebDavWagon 370 { 371 private static final String TIMEOUT_TRIGGER = "timeout"; 372 373 protected CloseableHttpResponse execute( HttpUriRequest httpRequestBase ) 374 throws HttpException, IOException 375 { 376 if ( httpRequestBase.getURI().getPath().contains( TIMEOUT_TRIGGER ) ) 377 { 378 throw new SocketTimeoutException( "Timeout triggered by request for '" + httpRequestBase.getURI().getPath() + "'" ); 379 } 380 else 381 { 382 return super.execute( httpRequestBase ); 383 } 384 } 385 } 386 387 public void testWagonContinuesOnPutFailureIfPropertySet() 388 throws Exception 389 { 390 setupWagonTestingFixtures(); 391 392 setupRepositories(); 393 394 File testFile = getTempFile(); 395 396 String continueOnFailureProperty = WebDavWagon.CONTINUE_ON_FAILURE_PROPERTY; 397 System.setProperty( continueOnFailureProperty, "true" ); 398 399 WebDavWagon wagon = new TimeoutSimulatingWagon(); 400 wagon.connect( testRepository, getAuthInfo() ); 401 402 try 403 { 404 String filename = TimeoutSimulatingWagon.TIMEOUT_TRIGGER + ".txt"; 405 406 wagon.put( testFile, filename ); 407 } 408 finally 409 { 410 wagon.disconnect(); 411 412 System.clearProperty( continueOnFailureProperty ); 413 414 tearDownWagonTestingFixtures(); 415 } 416 } 417 418 @Override 419 protected boolean supportPreemptiveAuthenticationPut() 420 { 421 return false; 422 } 423 424 @Override 425 protected boolean supportPreemptiveAuthenticationGet() 426 { 427 return false; 428 } 429 430 @Override 431 protected boolean supportProxyPreemptiveAuthentication() 432 { 433 return true; 434 } 435 436 protected void testPreemptiveAuthenticationGet( TestSecurityHandler sh, boolean preemptive ) 437 { 438 if ( preemptive ) 439 { 440 assertEquals( "testPreemptiveAuthenticationGet preemptive=true: expected 1 request, got " 441 + sh.handlerRequestResponses, 1, sh.handlerRequestResponses.size() ); 442 assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 0 ).responseCode ); 443 } 444 else 445 { 446 assertEquals( "testPreemptiveAuthenticationGet preemptive=false: expected 2 requests (401,200), got " 447 + sh.handlerRequestResponses, 2, sh.handlerRequestResponses.size() ); 448 assertEquals( HttpServletResponse.SC_UNAUTHORIZED, sh.handlerRequestResponses.get( 0 ).responseCode ); 449 assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 1 ).responseCode ); 450 } 451 } 452 453 protected void testPreemptiveAuthenticationPut( TestSecurityHandler sh, boolean preemptive ) 454 { 455 if ( preemptive ) 456 { 457 assertEquals( "testPreemptiveAuthenticationPut preemptive=true: expected 2 requests (200,201), got " 458 + sh.handlerRequestResponses, 2, sh.handlerRequestResponses.size() ); 459 assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 0 ).responseCode ); 460 assertEquals( HttpServletResponse.SC_CREATED, sh.handlerRequestResponses.get( 1 ).responseCode ); 461 } 462 else 463 { 464 assertEquals( "testPreemptiveAuthenticationPut preemptive=false: expected 3 requests (401,200,201), got " 465 + sh.handlerRequestResponses, 3, sh.handlerRequestResponses.size() ); 466 assertEquals( HttpServletResponse.SC_UNAUTHORIZED, sh.handlerRequestResponses.get( 0 ).responseCode ); 467 assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 1 ).responseCode ); 468 assertEquals( HttpServletResponse.SC_CREATED, sh.handlerRequestResponses.get( 2 ).responseCode ); 469 } 470 } 471 472 473 /* This method cannot be reasonable used to represend GET and PUT for WebDAV, it would contain too much 474 * duplicate code. Leave as-is, but don't use it. 475 */ 476 protected void testPreemptiveAuthentication( TestSecurityHandler sh, boolean preemptive ) 477 { 478 if ( preemptive ) 479 { 480 assertEquals( "testPreemptiveAuthentication preemptive=false: expected 2 requests (200,.), got " 481 + sh.handlerRequestResponses, 2, sh.handlerRequestResponses.size() ); 482 assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 0 ).responseCode ); 483 } 484 else 485 { 486 assertEquals( "testPreemptiveAuthentication preemptive=false: expected 3 requests (401,200,200), got " 487 + sh.handlerRequestResponses, 3, sh.handlerRequestResponses.size() ); 488 assertEquals( HttpServletResponse.SC_UNAUTHORIZED, sh.handlerRequestResponses.get( 0 ).responseCode ); 489 assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 1 ).responseCode ); 490 assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 2 ).responseCode ); 491 492 } 493 } 494 495 @Override 496 protected void checkRequestResponseForRedirectPutWithFullUrl( RedirectHandler redirectHandler, 497 PutHandler putHandler ) 498 { 499 assertEquals( "found:" + putHandler.handlerRequestResponses, 1, putHandler.handlerRequestResponses.size() ); 500 assertEquals( "found:" + putHandler.handlerRequestResponses, HttpServletResponse.SC_CREATED, 501 putHandler.handlerRequestResponses.get( 0 ).responseCode ); 502 assertEquals( "found:" + redirectHandler.handlerRequestResponses, 2, 503 redirectHandler.handlerRequestResponses.size() ); 504 assertEquals( "found:" + redirectHandler.handlerRequestResponses, HttpServletResponse.SC_SEE_OTHER, 505 redirectHandler.handlerRequestResponses.get( 0 ).responseCode ); 506 } 507 508 @Override 509 protected void checkRequestResponseForRedirectPutWithRelativeUrl( RedirectHandler redirectHandler, 510 PutHandler putHandler ) 511 { 512 assertEquals( "found:" + putHandler.handlerRequestResponses, 0, putHandler.handlerRequestResponses.size() ); 513 514 assertEquals( "found:" + redirectHandler.handlerRequestResponses, 4, 515 redirectHandler.handlerRequestResponses.size() ); 516 assertEquals( "found:" + redirectHandler.handlerRequestResponses, HttpServletResponse.SC_SEE_OTHER, 517 redirectHandler.handlerRequestResponses.get( 0 ).responseCode ); 518 assertEquals( "found:" + redirectHandler.handlerRequestResponses, HttpServletResponse.SC_OK, 519 redirectHandler.handlerRequestResponses.get( 1 ).responseCode ); 520 assertEquals( "found:" + redirectHandler.handlerRequestResponses, HttpServletResponse.SC_SEE_OTHER, 521 redirectHandler.handlerRequestResponses.get( 2 ).responseCode ); 522 523 } 524 525 @Override 526 protected void verifyWagonExceptionMessage( Exception e, int forStatusCode, String forUrl, String forReasonPhrase ) 527 { 528 Repository repo = new Repository( "test-geturl", forUrl ); 529 String expectedMessageUrl = ( new WebDavWagon() ).getURL( repo ); 530 super.verifyWagonExceptionMessage( e, forStatusCode, expectedMessageUrl, forReasonPhrase ); 531 } 532}