View Javadoc
1   package org.apache.maven.wagon.providers.webdav;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
5    * agreements. See the NOTICE file distributed with this work for additional information regarding
6    * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance with the License. You may obtain a
8    * copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software distributed under the License
13   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14   * or implied. See the License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  
18  import it.could.webdav.DAVServlet;
19  import org.apache.http.HttpException;
20  import org.apache.http.client.methods.CloseableHttpResponse;
21  import org.apache.http.client.methods.HttpRequestBase;
22  import org.apache.http.client.methods.HttpUriRequest;
23  import org.apache.maven.wagon.ResourceDoesNotExistException;
24  import org.apache.maven.wagon.StreamingWagon;
25  import org.apache.maven.wagon.TransferFailedException;
26  import org.apache.maven.wagon.Wagon;
27  import org.apache.maven.wagon.http.HttpWagonTestCase;
28  import org.apache.maven.wagon.repository.Repository;
29  import org.apache.maven.wagon.resource.Resource;
30  import org.apache.maven.wagon.shared.http.HttpConfiguration;
31  import org.apache.maven.wagon.shared.http.HttpMethodConfiguration;
32  import org.eclipse.jetty.server.Server;
33  import org.eclipse.jetty.servlet.ServletContextHandler;
34  import org.eclipse.jetty.servlet.ServletHolder;
35  
36  import java.io.File;
37  import java.io.IOException;
38  import java.net.SocketTimeoutException;
39  import java.util.List;
40  import java.util.Properties;
41  
42  import javax.servlet.http.HttpServletResponse;
43  
44  /*
45   * WebDAV Wagon Test
46   *
47   * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
48   *
49   * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
50   */
51  public class WebDavWagonTest
52      extends HttpWagonTestCase
53  {
54  
55      @Override
56      protected Wagon getWagon()
57          throws Exception
58      {
59          WebDavWagon wagon = (WebDavWagon) super.getWagon();
60          wagon.setHttpConfiguration(
61              new HttpConfiguration() //
62                  .setPut( new HttpMethodConfiguration().setUsePreemptive( true ) ));
63          return wagon;
64      }
65  
66      protected String getTestRepositoryUrl()
67          throws IOException
68      {
69          return getProtocol() + "://localhost:" + getTestRepositoryPort() + "/newfolder/folder2/";
70      }
71  
72      protected String getProtocol()
73      {
74          return "dav";
75      }
76  
77      protected ServletContextHandler createContext( Server server, File repositoryDirectory )
78          throws IOException
79      {
80          ServletContextHandler dav = new ServletContextHandler( ServletContextHandler.SESSIONS );
81          ServletHolder davServletHolder = new ServletHolder( new DAVServlet() );
82          davServletHolder.setInitParameter( "rootPath", repositoryDirectory.getAbsolutePath() );
83          davServletHolder.setInitParameter( "xmlOnly", "false" );
84          dav.addServlet( davServletHolder, "/*" );
85          return dav;
86      }
87  
88      protected long getExpectedLastModifiedOnGet( Repository repository, Resource resource )
89      {
90          File file = new File( getDavRepository(), resource.getName() );
91          return ( file.lastModified() / 1000L ) * 1000L;
92      }
93  
94  
95      private File getDavRepository()
96      {
97          return getTestFile( "target/test-output/http-repository/newfolder/folder2" );
98      }
99  
100     private void assertURL( String userUrl, String expectedUrl )
101     {
102         Repository repo = new Repository( "test-geturl", userUrl );
103         String actualUrl = ( new WebDavWagon() ).getURL( repo );
104         assertEquals( "WebDavWagon.getURL(" + userUrl + ")", expectedUrl, actualUrl );
105     }
106 
107     /**
108      * Tests the maven 2.0.x way to define a webdav URL without SSL.
109      */
110     public void testGetURLDavHttp()
111     {
112         assertURL( "dav:http://localhost:" + getTestRepositoryPort() + "/dav/",
113                    "http://localhost:" + getTestRepositoryPort() + "/dav/" );
114     }
115 
116     /**
117      * Tests the maven 2.0.x way to define a webdav URL with SSL.
118      */
119     public void testGetURLDavHttps()
120     {
121         assertURL( "dav:https://localhost:" + getTestRepositoryPort() + "/dav/",
122                    "https://localhost:" + getTestRepositoryPort() + "/dav/" );
123     }
124 
125     /**
126      * Tests the URI spec way of defining a webdav URL without SSL.
127      */
128     public void testGetURLDavUri()
129     {
130         assertURL( "dav://localhost:" + getTestRepositoryPort() + "/dav/",
131                    "http://localhost:" + getTestRepositoryPort() + "/dav/" );
132     }
133 
134     /**
135      * Tests the URI spec way of defining a webdav URL with SSL.
136      */
137     public void testGetURLDavUriWithSsl()
138     {
139         assertURL( "davs://localhost:" + getTestRepositoryPort() + "/dav/",
140                    "https://localhost:" + getTestRepositoryPort() + "/dav/" );
141     }
142 
143     /**
144      * Tests the URI spec way of defining a webdav URL without SSL.
145      */
146     public void testGetURLDavPlusHttp()
147     {
148         assertURL( "dav+https://localhost:" + getTestRepositoryPort() + "/dav/",
149                    "https://localhost:" + getTestRepositoryPort() + "/dav/" );
150     }
151 
152     /**
153      * Tests the URI spec way of defining a webdav URL with SSL.
154      */
155     public void testGetURLDavPlusHttps()
156     {
157         assertURL( "dav+https://localhost:" + getTestRepositoryPort() + "/dav/",
158                    "https://localhost:" + getTestRepositoryPort() + "/dav/" );
159     }
160 
161     public void testMkdirs()
162         throws Exception
163     {
164         setupRepositories();
165 
166         setupWagonTestingFixtures();
167 
168         WebDavWagon wagon = (WebDavWagon) getWagon();
169         wagon.connect( testRepository, getAuthInfo() );
170 
171         try
172         {
173             File dir = getRepositoryDirectory();
174 
175             // check basedir also doesn't exist and will need to be created
176             dir = new File( dir, testRepository.getBasedir() );
177             assertFalse( dir.exists() );
178 
179             // test leading /
180             assertFalse( new File( dir, "foo" ).exists() );
181             wagon.mkdirs( "/foo" );
182             assertTrue( new File( dir, "foo" ).exists() );
183 
184             // test trailing /
185             assertFalse( new File( dir, "bar" ).exists() );
186             wagon.mkdirs( "bar/" );
187             assertTrue( new File( dir, "bar" ).exists() );
188 
189             // test when already exists
190             wagon.mkdirs( "bar" );
191 
192             // test several parts
193             assertFalse( new File( dir, "1/2/3/4" ).exists() );
194             wagon.mkdirs( "1/2/3/4" );
195             assertTrue( new File( dir, "1/2/3/4" ).exists() );
196 
197             // test additional part and trailing /
198             assertFalse( new File( dir, "1/2/3/4/5" ).exists() );
199             wagon.mkdirs( "1/2/3/4/5/" );
200             assertTrue( new File( dir, "1/2/3/4" ).exists() );
201         }
202         finally
203         {
204             wagon.disconnect();
205 
206             tearDownWagonTestingFixtures();
207         }
208     }
209 
210     public void testMkdirsWithNoBasedir()
211         throws Exception
212     {
213         // WAGON-244
214         setupRepositories();
215 
216         setupWagonTestingFixtures();
217 
218         // reconstruct with no basedir
219         testRepository.setUrl(
220             testRepository.getProtocol() + "://" + testRepository.getHost() + ":" + testRepository.getPort() );
221 
222         WebDavWagon wagon = (WebDavWagon) getWagon();
223         wagon.connect( testRepository, getAuthInfo() );
224 
225         try
226         {
227             File dir = getRepositoryDirectory();
228 
229             // check basedir also doesn't exist and will need to be created
230             dir = new File( dir, testRepository.getBasedir() );
231             assertTrue( dir.exists() );
232 
233             // test leading /
234             assertFalse( new File( dir, "foo" ).exists() );
235             wagon.mkdirs( "/foo" );
236             assertTrue( new File( dir, "foo" ).exists() );
237         }
238         finally
239         {
240             wagon.disconnect();
241 
242             tearDownWagonTestingFixtures();
243         }
244     }
245 
246     protected void setHttpHeaders( StreamingWagon wagon, Properties properties )
247     {
248         ( (WebDavWagon) wagon ).setHttpHeaders( properties );
249     }
250 
251     /**
252      * Make sure Wagon WebDAV can detect remote directory
253      *
254      * @throws Exception
255      */
256     public void testWagonWebDavGetFileList()
257         throws Exception
258     {
259         setupRepositories();
260 
261         setupWagonTestingFixtures();
262 
263         String dirName = "file-list";
264 
265         String filenames[] =
266             new String[]{ "test-resource.txt", "test-resource.pom", "test-resource b.txt", "more-resources.dat" };
267 
268         for ( int i = 0; i < filenames.length; i++ )
269         {
270             putFile( dirName + "/" + filenames[i], dirName + "/" + filenames[i], filenames[i] + "\n" );
271         }
272 
273         String dirnames[] = new String[]{ "test-dir1", "test-dir2" };
274 
275         for ( int i = 0; i < dirnames.length; i++ )
276         {
277             new File( getDavRepository(), dirName + "/" + dirnames[i] ).mkdirs();
278         }
279 
280         Wagon wagon = getWagon();
281 
282         wagon.connect( testRepository, getAuthInfo() );
283 
284         List<String> list = wagon.getFileList( dirName );
285 
286         assertNotNull( "file list should not be null.", list );
287         assertEquals( "file list should contain 6 items", 6, list.size() );
288 
289         for ( int i = 0; i < filenames.length; i++ )
290         {
291             assertTrue( "Filename '" + filenames[i] + "' should be in list.", list.contains( filenames[i] ) );
292         }
293 
294         for ( int i = 0; i < dirnames.length; i++ )
295         {
296             assertTrue( "Directory '" + dirnames[i] + "' should be in list.", list.contains( dirnames[i] + "/" ) );
297         }
298 
299         ///////////////////////////////////////////////////////////////////////////
300         list = wagon.getFileList( "" );
301         assertNotNull( "file list should not be null.", list );
302         assertEquals( "file list should contain 1 items", 1, list.size() );
303 
304         ///////////////////////////////////////////////////////////////////////////
305         list = wagon.getFileList( dirName + "/test-dir1" );
306         assertNotNull( "file list should not be null.", list );
307         assertEquals( "file list should contain 0 items", 0, list.size() );
308 
309         /////////////////////////////////////////////////////////////////////////////
310         try
311         {
312             list = wagon.getFileList( dirName + "/test-dir-bogus" );
313             fail( "Exception expected" );
314         }
315         catch ( ResourceDoesNotExistException e )
316         {
317 
318         }
319 
320         wagon.disconnect();
321 
322         tearDownWagonTestingFixtures();
323     }
324 
325 
326     public void testWagonFailsOnPutFailureByDefault()
327         throws Exception
328     {
329         setupRepositories();
330 
331         setupWagonTestingFixtures();
332 
333         File testFile = getTempFile();
334 
335         System.clearProperty( WebDavWagon.CONTINUE_ON_FAILURE_PROPERTY );
336 
337         WebDavWagon wagon = new TimeoutSimulatingWagon();
338         wagon.connect( testRepository, getAuthInfo() );
339 
340         try
341         {
342             String filename = TimeoutSimulatingWagon.TIMEOUT_TRIGGER + ".txt";
343 
344             try
345             {
346                 wagon.put( testFile, filename );
347                 fail( "Exception expected" );
348             }
349             catch ( TransferFailedException e )
350             {
351 
352             }
353         }
354         finally
355         {
356             wagon.disconnect();
357 
358             tearDownWagonTestingFixtures();
359         }
360     }
361 
362     private File getTempFile()
363         throws IOException
364     {
365         File inputFile = File.createTempFile( "test-resource", ".txt" );
366         inputFile.deleteOnExit();
367         return inputFile;
368     }
369 
370     private static class TimeoutSimulatingWagon
371         extends WebDavWagon
372     {
373         private static final String TIMEOUT_TRIGGER = "timeout";
374 
375         protected CloseableHttpResponse execute( HttpUriRequest httpRequestBase )
376             throws HttpException, IOException
377         {
378             if ( httpRequestBase.getURI().getPath().contains( TIMEOUT_TRIGGER ) )
379             {
380                 throw new SocketTimeoutException( "Timeout triggered by request for '" + httpRequestBase.getURI().getPath() + "'" );
381             }
382             else
383             {
384                 return super.execute( httpRequestBase );
385             }
386         }
387     }
388 
389     public void testWagonContinuesOnPutFailureIfPropertySet()
390         throws Exception
391     {
392         setupRepositories();
393 
394         setupWagonTestingFixtures();
395 
396         File testFile = getTempFile();
397 
398         String continueOnFailureProperty = WebDavWagon.CONTINUE_ON_FAILURE_PROPERTY;
399         System.setProperty( continueOnFailureProperty, "true" );
400 
401         WebDavWagon wagon = new TimeoutSimulatingWagon();
402         wagon.connect( testRepository, getAuthInfo() );
403 
404         try
405         {
406             String filename = TimeoutSimulatingWagon.TIMEOUT_TRIGGER + ".txt";
407 
408             wagon.put( testFile, filename );
409         }
410         finally
411         {
412             wagon.disconnect();
413 
414             System.clearProperty( continueOnFailureProperty );
415 
416             tearDownWagonTestingFixtures();
417         }
418     }
419 
420     @Override
421     protected boolean supportPreemptiveAuthenticationPut()
422     {
423         return true;
424     }
425 
426     @Override
427     protected boolean supportPreemptiveAuthenticationGet()
428     {
429         return false;
430     }
431 
432     @Override
433     protected boolean supportProxyPreemptiveAuthentication()
434     {
435         return true;
436     }
437 
438     protected void testPreemptiveAuthenticationGet( TestSecurityHandler sh, boolean preemptive )
439     {
440         if ( preemptive )
441         {
442             assertEquals( "testPreemptiveAuthenticationGet preemptive=true: expected 1 request, got "
443                 + sh.handlerRequestResponses, 1, sh.handlerRequestResponses.size() );
444             assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 0 ).responseCode );
445         }
446         else
447         {
448             assertEquals( "testPreemptiveAuthenticationGet preemptive=false: expected 2 requests (401,200), got "
449                 + sh.handlerRequestResponses, 2, sh.handlerRequestResponses.size() );
450             assertEquals( HttpServletResponse.SC_UNAUTHORIZED, sh.handlerRequestResponses.get( 0 ).responseCode );
451             assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 1 ).responseCode );
452         }
453     }
454 
455     protected void testPreemptiveAuthenticationPut( TestSecurityHandler sh, boolean preemptive )
456     {
457         if ( preemptive )
458         {
459             assertEquals( "testPreemptiveAuthenticationPut preemptive=true: expected 2 requests (200,201), got "
460                 + sh.handlerRequestResponses, 2, sh.handlerRequestResponses.size() );
461             assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 0 ).responseCode );
462             assertEquals( HttpServletResponse.SC_CREATED, sh.handlerRequestResponses.get( 1 ).responseCode );
463         }
464         else
465         {
466             assertEquals( "testPreemptiveAuthenticationPut preemptive=false: expected 3 requests (401,200,201), got "
467                 + sh.handlerRequestResponses, 3, sh.handlerRequestResponses.size() );
468             assertEquals( HttpServletResponse.SC_UNAUTHORIZED, sh.handlerRequestResponses.get( 0 ).responseCode );
469             assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 1 ).responseCode );
470             assertEquals( HttpServletResponse.SC_CREATED, sh.handlerRequestResponses.get( 2 ).responseCode );
471         }
472     }
473 
474 
475     /* This method cannot be reasonable used to represend GET and PUT for WebDAV, it would contain too much
476      * duplicate code. Leave as-is, but don't use it.
477      */
478     protected void testPreemptiveAuthentication( TestSecurityHandler sh, boolean preemptive )
479     {
480         if ( preemptive )
481         {
482             assertEquals( "testPreemptiveAuthentication preemptive=false: expected 2 requests (200,.), got "
483                 + sh.handlerRequestResponses, 2, sh.handlerRequestResponses.size() );
484             assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 0 ).responseCode );
485         }
486         else
487         {
488             assertEquals( "testPreemptiveAuthentication preemptive=false: expected 3 requests (401,200,200), got "
489                 + sh.handlerRequestResponses, 3, sh.handlerRequestResponses.size() );
490             assertEquals( HttpServletResponse.SC_UNAUTHORIZED, sh.handlerRequestResponses.get( 0 ).responseCode );
491             assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 1 ).responseCode );
492             assertEquals( HttpServletResponse.SC_OK, sh.handlerRequestResponses.get( 2 ).responseCode );
493 
494         }
495     }
496 
497     @Override
498     protected void checkRequestResponseForRedirectPutWithFullUrl( RedirectHandler redirectHandler,
499                                                                   PutHandler putHandler )
500     {
501         assertEquals( "found:" + putHandler.handlerRequestResponses, 1, putHandler.handlerRequestResponses.size() );
502         assertEquals( "found:" + putHandler.handlerRequestResponses, HttpServletResponse.SC_CREATED,
503                       putHandler.handlerRequestResponses.get( 0 ).responseCode );
504         assertEquals( "found:" + redirectHandler.handlerRequestResponses, 3,
505                       redirectHandler.handlerRequestResponses.size() );
506         assertEquals( "found:" + redirectHandler.handlerRequestResponses, HttpServletResponse.SC_SEE_OTHER,
507                       redirectHandler.handlerRequestResponses.get( 0 ).responseCode );
508     }
509 
510     @Override
511     protected void checkRequestResponseForRedirectPutWithRelativeUrl( RedirectHandler redirectHandler,
512                                                                       PutHandler putHandler )
513     {
514         assertEquals( "found:" + putHandler.handlerRequestResponses, 0, putHandler.handlerRequestResponses.size() );
515 
516         assertEquals( "found:" + redirectHandler.handlerRequestResponses, 6,
517                       redirectHandler.handlerRequestResponses.size() );
518         assertEquals( "found:" + redirectHandler.handlerRequestResponses, HttpServletResponse.SC_SEE_OTHER,
519                       redirectHandler.handlerRequestResponses.get( 0 ).responseCode );
520         assertEquals( "found:" + redirectHandler.handlerRequestResponses, HttpServletResponse.SC_OK,
521                       redirectHandler.handlerRequestResponses.get( 1 ).responseCode );
522         assertEquals( "found:" + redirectHandler.handlerRequestResponses, HttpServletResponse.SC_SEE_OTHER,
523                       redirectHandler.handlerRequestResponses.get( 2 ).responseCode );
524 
525     }
526 
527 }