1   package org.apache.maven.shared.model.fileset.util;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.net.URL;
25  import java.net.URLDecoder;
26  import java.util.HashSet;
27  import java.util.Iterator;
28  import java.util.Set;
29  
30  import junit.framework.Assert;
31  import junit.framework.TestCase;
32  
33  import org.apache.maven.shared.model.fileset.FileSet;
34  import org.codehaus.plexus.util.FileUtils;
35  import org.codehaus.plexus.util.cli.CommandLineException;
36  import org.codehaus.plexus.util.cli.Commandline;
37  
38  /**
39   * Test the FileSet
40   *
41   * @version $Id: FileSetUtilsTest.html 886882 2013-11-16 21:55:43Z hboutemy $
42   */
43  public class FileSetUtilsTest
44      extends TestCase
45  {
46      private Set testDirectories = new HashSet();
47  
48      private Set linkFiles = new HashSet();
49  
50      /** {@inheritDoc} */
51      public void tearDown()
52          throws IOException
53      {
54          for ( Iterator it = linkFiles.iterator(); it.hasNext(); )
55          {
56              File linkFile = (File) it.next();
57  
58              linkFile.delete();
59          }
60  
61          for ( Iterator it = testDirectories.iterator(); it.hasNext(); )
62          {
63              File dir = (File) it.next();
64  
65              FileUtils.deleteDirectory( dir );
66          }
67      }
68  
69      /**
70       * @throws IOException if any
71       */
72      public void testGetIncludedFiles()
73          throws IOException
74      {
75          File directory = setupTestDirectory( "testGetIncludedFiles" );
76  
77          FileSet set = new FileSet();
78          set.setDirectory( directory.getPath() );
79          set.addInclude( "**/included.txt" );
80  
81          FileSetManager fileSetManager = new FileSetManager();
82  
83          String[] included = fileSetManager.getIncludedFiles( set );
84  
85          Assert.assertEquals( 1, included.length );
86      }
87  
88      /**
89       * @throws IOException if any
90       * @throws InterruptedException if any
91       * @throws CommandLineException if any
92       */
93      public void testIncludesDontFollowSymlinks()
94          throws IOException, InterruptedException, CommandLineException
95      {
96          File directory = setupTestDirectory( "testIncludesDontFollowSymlinks" );
97          File subdir = new File( directory, directory.getName() );
98  
99          if ( !createSymlink( directory, subdir ) )
100         {
101             // assume failure to create a sym link is because the system does not support them
102             // and not because the sym link creation failed.
103             return;
104         }
105 
106         FileSet set = new FileSet();
107         set.setDirectory( directory.getPath() );
108         set.addInclude( "**/included.txt" );
109         set.setFollowSymlinks( false );
110 
111         FileSetManager fileSetManager = new FileSetManager();
112 
113         String[] included = fileSetManager.getIncludedFiles( set );
114 
115         Assert.assertEquals( 1, included.length );
116     }
117 
118     /**
119      * @throws IOException if any
120      * @throws InterruptedException if any
121      * @throws CommandLineException if any
122      */
123     public void testDeleteDontFollowSymlinks()
124         throws IOException, InterruptedException, CommandLineException
125     {
126         File directory = setupTestDirectory( "testDeleteDontFollowSymlinks" );
127         File subdir = new File( directory, directory.getName() );
128 
129         if ( !createSymlink( directory, subdir ) )
130         {
131             // assume failure to create a sym link is because the system does not support them
132             // and not because the sym link creation failed.
133             return;
134         }
135 
136         FileSet set = new FileSet();
137         set.setDirectory( directory.getPath() );
138         set.addInclude( "**/included.txt" );
139         set.addInclude( "**/" + subdir.getName() );
140         set.setFollowSymlinks( false );
141 
142         FileSetManager fileSetManager = new FileSetManager();
143 
144         fileSetManager.delete( set );
145 
146         Assert.assertFalse( subdir.exists() );
147     }
148 
149     /**
150      * @throws IOException if any
151      */
152     public void testDelete()
153         throws IOException
154     {
155         File directory = setupTestDirectory( "testDelete" );
156         File subdirFile = new File( directory, "subdir/excluded.txt" );
157 
158         FileSet set = new FileSet();
159         set.setDirectory( directory.getPath() );
160         set.addInclude( "**/included.txt" );
161         set.addInclude( "**/subdir" );
162 
163         FileSetManager fileSetManager = new FileSetManager();
164 
165         fileSetManager.delete( set );
166 
167         Assert.assertFalse( "file in marked subdirectory still exists.", subdirFile.exists() );
168     }
169 
170     /**
171      * @throws Exception if any
172      */
173     public void testDeleteDanglingSymlink()
174         throws Exception
175     {
176         File directory = setupTestDirectory( "testDeleteDanglingSymlink" );
177         File targetFile = new File( directory, "test.txt" );
178         File linkFile = new File( directory, "symlink" );
179 
180         if ( !createSymlink( targetFile, linkFile ) )
181         {
182             // symlinks apparently not supported, skip test
183             return;
184         }
185         targetFile.delete();
186 
187         FileSet set = new FileSet();
188         set.setDirectory( directory.getPath() );
189         set.addInclude( "**" );
190 
191         FileSetManager fileSetManager = new FileSetManager();
192 
193         fileSetManager.delete( set );
194 
195         Assert.assertFalse( "directory still exists", directory.exists() );
196     }
197 
198     /**
199      * @throws Exception if any
200      */
201     public void testDeleteExcludeParentOfExcludedFile()
202         throws Exception
203     {
204         File directory = setupTestDirectory( "testDeleteExcludeParentOfExcludedFile" );
205 
206         FileSet set = new FileSet();
207         set.setDirectory( directory.getPath() );
208         set.addExclude( "*excluded*" );
209         set.setFollowSymlinks( true );
210 
211         FileSetManager fileSetManager = new FileSetManager();
212 
213         fileSetManager.delete( set );
214 
215         Assert.assertTrue( "excluded file has been deleted", new File( directory, "excluded.txt" ).exists() );
216     }
217 
218     /**
219      * @throws Exception if any
220      */
221     public void testDeleteExcludeParentOfExcludedDir()
222         throws Exception
223     {
224         File directory = setupTestDirectory( "testDeleteExcludeParentOfExcludedDir" );
225 
226         FileSet set = new FileSet();
227         set.setDirectory( directory.getPath() );
228         set.addExclude( "*excluded*" );
229         set.setFollowSymlinks( true );
230 
231         FileSetManager fileSetManager = new FileSetManager();
232 
233         fileSetManager.delete( set );
234 
235         Assert.assertTrue( "excluded directory has been deleted", new File( directory, "excluded" ).exists() );
236     }
237 
238     /**
239      * @throws Exception if any
240      */
241     public void testDeleteExcludeFollowSymlinks()
242         throws Exception
243     {
244         File directory = setupTestDirectory( "testDeleteExcludeFollowSymlinks" );
245 
246         FileSet set = new FileSet();
247         set.setDirectory( directory.getPath() );
248         set.addExclude( "*excluded*" );
249         set.setFollowSymlinks( true );
250 
251         FileSetManager fileSetManager = new FileSetManager();
252 
253         fileSetManager.delete( set );
254 
255         Assert.assertTrue( "excluded file has been deleted", new File( directory, "excluded.txt" ).exists() );
256         Assert.assertTrue( "excluded directory has been deleted", new File( directory, "excluded" ).exists() );
257         Assert.assertFalse( "included file has not been deleted", new File( directory, "included.txt" ).exists() );
258     }
259 
260     /**
261      * @throws Exception if any
262      */
263     public void testDeleteExcludeDontFollowSymlinks()
264         throws Exception
265     {
266         File directory = setupTestDirectory( "testDeleteExcludeDontFollowSymlinks" );
267 
268         FileSet set = new FileSet();
269         set.setDirectory( directory.getPath() );
270         set.addExclude( "*excluded*" );
271         set.setFollowSymlinks( false );
272 
273         FileSetManager fileSetManager = new FileSetManager();
274 
275         fileSetManager.delete( set );
276 
277         Assert.assertTrue( "excluded file has been deleted", new File( directory, "excluded.txt" ).exists() );
278         Assert.assertTrue( "excluded directory has been deleted", new File( directory, "excluded" ).exists() );
279         Assert.assertFalse( "included file has not been deleted", new File( directory, "included.txt" ).exists() );
280     }
281 
282     /**
283      * @throws Exception if any
284      */
285     public void testDeleteDontFollowSymlinksButDeleteThem()
286         throws Exception
287     {
288         File directory = setupTestDirectory( "testDeleteDontFollowSymlinksButDeleteThem" );
289 
290         createSymlink( new File( directory, "excluded" ), new File( directory, "dirlink" ) );
291         createSymlink( new File( directory, "excluded.txt" ), new File( directory, "filelink" ) );
292         createSymlink( new File( directory, "excluded" ), new File( directory, "dir0/dirlink" ) );
293         createSymlink( new File( directory, "excluded.txt" ), new File( directory, "dir1/filelink" ) );
294 
295         FileSet set = new FileSet();
296         set.setDirectory( directory.getPath() );
297         set.addExclude( "*excluded*" );
298         set.setFollowSymlinks( false );
299 
300         FileSetManager fileSetManager = new FileSetManager();
301 
302         fileSetManager.delete( set );
303 
304         Assert.assertTrue( "excluded file has been deleted", new File( directory, "excluded.txt" ).exists() );
305         Assert.assertTrue( "excluded directory has been deleted", new File( directory, "excluded" ).exists() );
306         Assert.assertFalse( "included dirlink has not been deleted", new File( directory, "dirlink" ).exists() );
307         Assert.assertFalse( "included filelink has not been deleted", new File( directory, "filelink" ).exists() );
308         Assert.assertFalse( "included directory has not been deleted", new File( directory, "dir0" ).exists() );
309         Assert.assertFalse( "included directory has not been deleted", new File( directory, "dir1" ).exists() );
310     }
311 
312     /**
313      * @param target The target file/directory of the symlink, must not be <code>null</code>.
314      * @param link The link to create, must not be <code>null</code>.
315      * @return
316      * @throws InterruptedException
317      * @throws CommandLineException
318      */
319     private boolean createSymlink( File target, File link )
320         throws InterruptedException, CommandLineException
321     {
322         if ( link.exists() )
323         {
324             link.delete();
325         }
326 
327         Commandline cli = new Commandline();
328         cli.setExecutable( "ln" );
329         cli.createArg().setValue( "-s" );
330         cli.createArg().setValue( target.getPath() );
331         cli.createArg().setValue( link.getPath() );
332 
333         int result = cli.execute().waitFor();
334 
335         linkFiles.add( link );
336 
337         return result == 0;
338     }
339 
340     /**
341      * @param directoryName
342      * @return
343      * @throws IOException
344      */
345     private File setupTestDirectory( String directoryName )
346         throws IOException
347     {
348         System.out.println( "Setting up directory for test: " + directoryName );
349 
350         URL sourceResource = getClass().getClassLoader().getResource( directoryName );
351 
352         if ( sourceResource == null )
353         {
354             Assert.fail( "Source directory for test: " + directoryName + " cannot be found." );
355         }
356 
357         File sourceDir = new File( URLDecoder.decode( sourceResource.getPath(), "UTF-8" ) );
358 
359         String basedir = System.getProperty( "basedir", System.getProperty( "user.dir" ) );
360         String testBase = System.getProperty( "testBase", "target/test-directories" );
361 
362         File testDir = new File( basedir, testBase + "/" + directoryName );
363         testDir.mkdirs();
364 
365         FileUtils.copyDirectoryStructure( sourceDir, testDir );
366 
367         testDirectories.add( testDir );
368 
369         return testDir;
370     }
371 }