1 19 20 package edu.umd.cs.findbugs.ba; 21 22 import java.io.File ; 23 import java.io.FileNotFoundException ; 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 import java.net.JarURLConnection ; 27 import java.net.MalformedURLException ; 28 import java.net.URL ; 29 import java.util.Enumeration ; 30 import java.util.LinkedHashMap ; 31 import java.util.LinkedList ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.zip.ZipFile ; 35 import java.util.zip.ZipEntry ; 36 37 import edu.umd.cs.findbugs.SourceLineAnnotation; 38 import edu.umd.cs.findbugs.SystemProperties; 39 40 45 public class SourceFinder { 46 private static final boolean DEBUG = SystemProperties.getBoolean("srcfinder.debug"); 47 private static final int CACHE_SIZE = 50; 48 49 52 53 58 private static class Cache extends LinkedHashMap <String , SourceFile> { 59 62 private static final long serialVersionUID = 1L; 63 64 @Override 65 protected boolean removeEldestEntry(Map.Entry <String , SourceFile> eldest) { 66 return size() >= CACHE_SIZE; 67 } 68 } 69 70 73 private interface SourceRepository { 74 public boolean contains(String fileName); 75 76 public boolean isPlatformDependent(); 77 78 public SourceFileDataSource getDataSource(String fileName); 79 } 80 81 84 private static class DirectorySourceRepository implements SourceRepository { 85 private String baseDir; 86 87 public DirectorySourceRepository(String baseDir) { 88 this.baseDir = baseDir; 89 } 90 91 @Override 92 public String toString() { 93 return "DirectorySourceRepository:" + baseDir; 94 } 95 public boolean contains(String fileName) { 96 File file = new File (getFullFileName(fileName)); 97 boolean exists = file.exists(); 98 if (DEBUG) System.out.println("Exists " + exists + " for " + file); 99 return exists; 100 } 101 102 public boolean isPlatformDependent() { 103 return true; 104 } 105 106 public SourceFileDataSource getDataSource(String fileName) { 107 return new FileSourceFileDataSource(getFullFileName(fileName)); 108 } 109 110 private String getFullFileName(String fileName) { 111 return baseDir + File.separator + fileName; 112 } 113 } 114 115 static class JarURLConnectionSourceRepository extends ZipSourceRepository { 116 117 public JarURLConnectionSourceRepository(String url) throws MalformedURLException , IOException { 118 super(((JarURLConnection ) new URL ("jar:" + url +"!/").openConnection()).getJarFile()); 119 120 if (DEBUG) { 121 System.out.println("JarURLConnectionSourceRepository entries"); 122 for(Enumeration <? extends ZipEntry > e = zipFile.entries(); e.hasMoreElements(); ) { 123 ZipEntry ze = e.nextElement(); 124 System.out.println(ze.getName()); 125 } 126 } 127 } 128 129 } 130 133 static class ZipSourceRepository implements SourceRepository { 134 ZipFile zipFile; 135 136 public ZipSourceRepository(ZipFile zipFile) { 137 this.zipFile = zipFile; 138 } 139 140 public boolean contains(String fileName) { 141 return zipFile.getEntry(fileName) != null; 142 } 143 144 public boolean isPlatformDependent() { 145 return false; 146 } 147 148 public SourceFileDataSource getDataSource(String fileName) { 149 return new ZipSourceFileDataSource(zipFile, fileName); 150 } 151 } 152 153 156 157 private List <SourceRepository> repositoryList; 158 private Cache cache; 159 160 163 164 167 public SourceFinder() { 168 if (DEBUG) System.out.println("Debugging SourceFinder"); 169 repositoryList = new LinkedList <SourceRepository>(); 170 cache = new Cache(); 171 } 172 173 176 public void setSourceBaseList(List <String > sourceBaseList) { 177 for (String repos : sourceBaseList) { 178 if (repos.endsWith(".zip") || repos.endsWith(".jar")) { 179 try { 181 if (repos.startsWith("http:") || repos.startsWith("https:") || repos.startsWith("file:")) 182 repositoryList.add(new JarURLConnectionSourceRepository(repos)); 183 else 184 repositoryList.add(new ZipSourceRepository(new ZipFile (repos))); 185 } catch (IOException e) { 186 } 188 } else { 189 repositoryList.add(new DirectorySourceRepository(repos)); 191 } 192 } 193 } 194 195 203 public InputStream openSource(String packageName, String fileName) throws IOException { 204 SourceFile sourceFile = findSourceFile(packageName, fileName); 205 return sourceFile.getInputStream(); 206 } 207 public InputStream openSource(SourceLineAnnotation source) throws IOException { 208 SourceFile sourceFile = findSourceFile(source); 209 return sourceFile.getInputStream(); 210 } 211 public SourceFile findSourceFile(SourceLineAnnotation source) throws IOException { 212 if (source.isSourceFileKnown()) 213 return findSourceFile(source.getPackageName(), source.getSourceFile()); 214 String packageName = source.getPackageName(); 215 String baseClassName = source.getClassName(); 216 int i = baseClassName.lastIndexOf('.'); 217 baseClassName = baseClassName.substring(i+1); 218 int j = baseClassName.indexOf("$"); 219 if (j >= 0) 220 baseClassName = baseClassName.substring(0,j); 221 return findSourceFile(packageName, baseClassName + ".java"); 222 223 } 224 232 public SourceFile findSourceFile(String packageName, String fileName) throws IOException { 233 237 241 String platformName = packageName.replace('.', File.separatorChar) + 243 (packageName.length() > 0 ? File.separator : "") + fileName; 244 String canonicalName = packageName.replace('.', '/') + 245 (packageName.length() > 0 ? "/" : "") + fileName; 246 247 SourceFile sourceFile = cache.get(canonicalName); 249 if (sourceFile != null) 250 return sourceFile; 251 252 if (DEBUG) System.out.println("Trying " + fileName + " in package " + packageName + "..."); 254 for (SourceRepository repos : repositoryList) { 256 fileName = repos.isPlatformDependent() ? platformName : canonicalName; 257 if (DEBUG) System.out.println("Looking in " + repos + " for " + fileName); 258 if (repos.contains(fileName)) { 259 sourceFile = new SourceFile(repos.getDataSource(fileName)); 261 cache.put(canonicalName, sourceFile); return sourceFile; 263 } 264 } 265 266 throw new FileNotFoundException ("Can't find source file " + fileName); 267 } 268 } 269 270 | Popular Tags |