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