001 package AST; 002 003 import java.util.HashSet; 004 import java.io.File; 005 import java.util.*; 006 import beaver.*; 007 import java.util.ArrayList; 008 import java.util.zip.*; 009 import java.io.*; 010 import java.io.FileNotFoundException; 011 import java.util.Collection; 012 013 /** 014 * @ast class 015 * 016 */ 017 public class FolderPart extends PathPart { 018 019 020 /** 021 * Maps package names to a collection of the names of files in 022 * the corresponding package directory. 023 */ 024 private Map<String, Collection<String>> packageMap = 025 new HashMap<String, Collection<String>>(); 026 027 028 029 /** 030 * The root folder of this path part. 031 */ 032 private final File folder; 033 034 035 036 public FolderPart(File folder) { 037 this.folder = folder; 038 } 039 040 041 042 /** 043 * @param name The qualified package name 044 * @return <code>true</code> if the given package exists in this source 045 * folder 046 */ 047 public boolean hasPackage(String name) { 048 return !filesInPackage(name).isEmpty(); 049 } 050 051 052 053 public boolean hasCompilationUnit(String canonicalName) { 054 int index = canonicalName.lastIndexOf('.'); 055 String packageName = index == -1 ? "" : canonicalName.substring(0, index); 056 String typeName = canonicalName.substring(index + 1, canonicalName.length()); 057 String fileName = typeName + fileSuffix(); 058 return filesInPackage(packageName).contains(fileName); 059 } 060 061 062 063 /** 064 * We need to use getCanonicalFile in order to get the case-sensitive 065 * package name on case-insensitive file systems or we might incorrectly 066 * report a package name conflict. 067 * 068 * NB: This does not work well with symlinks! 069 * 070 * @param packageName The qualified name of the package 071 * @return The names of the files and folders in the package 072 */ 073 private Collection<String> filesInPackage(String packageName) { 074 if (!packageMap.containsKey(packageName)) { 075 int index = packageName.lastIndexOf('.'); 076 String name = packageName.substring(index == -1 ? 0 : index+1); 077 String folderName = packageName.replace('.', File.separatorChar); 078 File pkgFolder = new File(folder, folderName); 079 Collection<String> fileSet = Collections.emptyList(); 080 try { 081 // Make sure that there exists a directory with the same name 082 // (case-sensitive) as the requested package 083 File canonical = pkgFolder.getCanonicalFile(); 084 if (canonical.isDirectory() && (packageName.isEmpty() || 085 canonical.getName().equals(name))) { 086 String[] files = canonical.list(); 087 if (files.length > 0) { 088 fileSet = new HashSet<String>(); 089 for (String file: files) { 090 fileSet.add(file); 091 } 092 } 093 } 094 } catch (Exception e) { 095 // Catch IOExceptions etc. 096 // if the exception was thrown by getCanonicalFile we will put 097 // the empty list in the packageMap, indicating that the package 098 // does not exist 099 } 100 packageMap.put(packageName, fileSet); 101 } 102 return packageMap.get(packageName); 103 } 104 105 106 107 public boolean selectCompilationUnit(String canonicalName) throws IOException { 108 if(hasCompilationUnit(canonicalName)) { 109 String typeName = canonicalName.replace('.', File.separatorChar); 110 String fileName = typeName + fileSuffix(); 111 File classFile = new File(folder, fileName); 112 if(classFile.isFile()) { 113 is = new FileInputStream(classFile); 114 age = classFile.lastModified(); 115 pathName = classFile.getPath(); 116 relativeName = fileName + fileSuffix(); 117 fullName = canonicalName; 118 return true; 119 } 120 } 121 return false; 122 } 123 124 125 126 @Override 127 public String toString() { 128 return folder.toString(); 129 } 130 131 132 }