FileUtil.java
001 package net.sourceforge.pmd.util;
002 
003 import java.io.File;
004 import java.io.FilenameFilter;
005 import java.io.IOException;
006 import java.util.ArrayList;
007 import java.util.Collections;
008 import java.util.Enumeration;
009 import java.util.List;
010 import java.util.zip.ZipEntry;
011 import java.util.zip.ZipFile;
012 
013 import net.sourceforge.pmd.util.datasource.DataSource;
014 import net.sourceforge.pmd.util.datasource.FileDataSource;
015 import net.sourceforge.pmd.util.datasource.ZipDataSource;
016 import net.sourceforge.pmd.util.filter.AndFilter;
017 import net.sourceforge.pmd.util.filter.Filter;
018 import net.sourceforge.pmd.util.filter.Filters;
019 import net.sourceforge.pmd.util.filter.OrFilter;
020 
021 /**
022  * This is a utility class for working with Files.
023  */
024 public final class FileUtil {
025 
026     private FileUtil() {}
027     
028     /**
029      * Helper method to get a filename without its extension
030      @param fileName String
031      @return String
032      */
033     public static String getFileNameWithoutExtension(String fileName) {
034         String name = fileName;
035 
036         int index = fileName.lastIndexOf('.');
037         if (index != -1) {
038             name = fileName.substring(0, index);
039         }
040 
041         return name;
042     }
043     
044     /**
045      * Collects a list of DataSources using a comma separated list of input file
046      * locations to process.  If a file location is a directory, the directory
047      * hierarchy will be traversed to look for files.  If a file location is a
048      * ZIP or Jar the archive will be scanned looking for files.  If a file
049      * location is a file, it will be used.  For each located file, a
050      * FilenameFilter is used to decide whether to return a DataSource.
051      *
052      @param fileLocations A comma-separated list of file locations.
053      @param filenameFilter  The FilenameFilter to apply to files.
054      @return A list of DataSources, one for each file collected.
055      */
056     public static List<DataSource> collectFiles(String fileLocations, FilenameFilter filenameFilter) {
057   List<DataSource> dataSources = new ArrayList<DataSource>();
058   for (String fileLocation : fileLocations.split(",")) {
059       collect(dataSources, fileLocation, filenameFilter);
060   }
061   return dataSources;
062     }
063 
064     private static List<DataSource> collect(List<DataSource> dataSources, String fileLocation,
065       FilenameFilter filenameFilter) {
066   File file = new File(fileLocation);
067   if (!file.exists()) {
068       throw new RuntimeException("File " + file.getName() " doesn't exist");
069   }
070   if (!file.isDirectory()) {
071       if (fileLocation.endsWith(".zip"|| fileLocation.endsWith(".jar")) {
072     ZipFile zipFile;
073     try {
074         zipFile = new ZipFile(fileLocation);
075         Enumeration<? extends ZipEntry> e = zipFile.entries();
076         while (e.hasMoreElements()) {
077       ZipEntry zipEntry = e.nextElement();
078       if (filenameFilter.accept(null, zipEntry.getName())) {
079           dataSources.add(new ZipDataSource(zipFile, zipEntry));
080       }
081         }
082     catch (IOException ze) {
083         throw new RuntimeException("Archive file " + file.getName() " can't be opened");
084     }
085       else {
086     dataSources.add(new FileDataSource(file));
087       }
088   else {
089       // Match files, or directories which are not excluded.
090       // FUTURE Make the excluded directories be some configurable option
091       Filter<File> filter = new OrFilter<File>(Filters.toFileFilter(filenameFilter)new AndFilter<File>(Filters
092         .getDirectoryFilter(), Filters.toNormalizedFileFilter(Filters.buildRegexFilterExcludeOverInclude(
093         null, Collections.singletonList("SCCS")))));
094       FileFinder finder = new FileFinder();
095       List<File> files = finder.findFilesFrom(file.getAbsolutePath(), Filters.toFilenameFilter(filter)true);
096       for (File f : files) {
097     dataSources.add(new FileDataSource(f));
098       }
099   }
100   return dataSources;
101     }
102 }