View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.util;
5   
6   import java.io.File;
7   import java.io.FilenameFilter;
8   import java.io.IOException;
9   import java.util.ArrayList;
10  import java.util.Collections;
11  import java.util.Enumeration;
12  import java.util.List;
13  import java.util.regex.Matcher;
14  import java.util.regex.Pattern;
15  import java.util.zip.ZipEntry;
16  import java.util.zip.ZipFile;
17  
18  import net.sourceforge.pmd.util.datasource.DataSource;
19  import net.sourceforge.pmd.util.datasource.FileDataSource;
20  import net.sourceforge.pmd.util.datasource.ZipDataSource;
21  import net.sourceforge.pmd.util.filter.AndFilter;
22  import net.sourceforge.pmd.util.filter.Filter;
23  import net.sourceforge.pmd.util.filter.Filters;
24  import net.sourceforge.pmd.util.filter.OrFilter;
25  
26  /**
27   * This is a utility class for working with Files.
28   */
29  public final class FileUtil {
30  
31      private FileUtil() {}
32  
33      /**
34       * Helper method to get a filename without its extension
35       * @param fileName String
36       * @return String
37       */
38      public static String getFileNameWithoutExtension(String fileName) {
39          String name = fileName;
40  
41          int index = fileName.lastIndexOf('.');
42          if (index != -1) {
43              name = fileName.substring(0, index);
44          }
45  
46          return name;
47      }
48  
49      /**
50       * Collects a list of DataSources using a comma separated list of input file
51       * locations to process.  If a file location is a directory, the directory
52       * hierarchy will be traversed to look for files.  If a file location is a
53       * ZIP or Jar the archive will be scanned looking for files.  If a file
54       * location is a file, it will be used.  For each located file, a
55       * FilenameFilter is used to decide whether to return a DataSource.
56       *
57       * @param fileLocations A comma-separated list of file locations.
58       * @param filenameFilter  The FilenameFilter to apply to files.
59       * @return A list of DataSources, one for each file collected.
60       */
61      public static List<DataSource> collectFiles(String fileLocations, FilenameFilter filenameFilter) {
62  	List<DataSource> dataSources = new ArrayList<DataSource>();
63  	for (String fileLocation : fileLocations.split(",")) {
64  	    collect(dataSources, fileLocation, filenameFilter);
65  	}
66  	return dataSources;
67      }
68  
69      private static List<DataSource> collect(List<DataSource> dataSources, String fileLocation,
70  	    FilenameFilter filenameFilter) {
71  	File file = new File(fileLocation);
72  	if (!file.exists()) {
73  	    throw new RuntimeException("File " + file.getName() + " doesn't exist");
74  	}
75  	if (!file.isDirectory()) {
76  	    if (fileLocation.endsWith(".zip") || fileLocation.endsWith(".jar")) {
77  		ZipFile zipFile;
78  		try {
79  		    zipFile = new ZipFile(fileLocation);
80  		    Enumeration<? extends ZipEntry> e = zipFile.entries();
81  		    while (e.hasMoreElements()) {
82  			ZipEntry zipEntry = e.nextElement();
83  			if (filenameFilter.accept(null, zipEntry.getName())) {
84  			    dataSources.add(new ZipDataSource(zipFile, zipEntry));
85  			}
86  		    }
87  		} catch (IOException ze) {
88  		    throw new RuntimeException("Archive file " + file.getName() + " can't be opened");
89  		}
90  	    } else {
91  		dataSources.add(new FileDataSource(file));
92  	    }
93  	} else {
94  	    // Match files, or directories which are not excluded.
95  	    // FUTURE Make the excluded directories be some configurable option
96  	    Filter<File> filter = new OrFilter<File>(Filters.toFileFilter(filenameFilter), new AndFilter<File>(Filters
97  		    .getDirectoryFilter(), Filters.toNormalizedFileFilter(Filters.buildRegexFilterExcludeOverInclude(
98  		    null, Collections.singletonList("SCCS")))));
99  	    FileFinder finder = new FileFinder();
100 	    List<File> files = finder.findFilesFrom(file.getAbsolutePath(), Filters.toFilenameFilter(filter), true);
101 	    for (File f : files) {
102 		dataSources.add(new FileDataSource(f));
103 	    }
104 	}
105 	return dataSources;
106     }
107 
108     /**
109      * Handy method to find a certain pattern into a file. While this method lives in the FileUtils, it was
110      * designed with with unit test in mind (to check result redirected into a file)
111      *
112      * @param file
113      * @param pattern
114      * @return
115      */
116     public static boolean findPatternInFile( final File file, final String pattern ) {
117 
118     	Pattern regexp = Pattern.compile(pattern);
119     	Matcher matcher = regexp.matcher("");
120 
121     	FileIterable it = new FileIterable(file);
122     	for ( String line : it ){
123     		matcher.reset( line ); //reset the input
124     		if ( matcher.find() )
125     			return true;
126     	}
127     	return false;
128     }
129 }