| 1 19 20 package edu.umd.cs.findbugs.ba; 21 22 import java.io.BufferedInputStream ; 23 import java.io.File ; 24 import java.io.FileInputStream ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.Serializable ; 28 import java.net.URL ; 29 import java.util.HashSet ; 30 import java.util.LinkedList ; 31 import java.util.List ; 32 import java.util.Set ; 33 import java.util.zip.ZipEntry ; 34 import java.util.zip.ZipFile ; 35 36 import org.apache.bcel.classfile.ClassFormatException; 37 import org.apache.bcel.classfile.ClassParser; 38 import org.apache.bcel.classfile.JavaClass; 39 40 import edu.umd.cs.findbugs.FindBugs; 41 import edu.umd.cs.findbugs.util.Archive; 42 43 50 public class URLClassPath implements Serializable { 51 private static final long serialVersionUID = 1L; 52 53 56 private interface Entry { 57 65 public InputStream openStream(String resourceName) throws IOException ; 66 67 70 public String getURL(); 71 72 75 public void close(); 76 } 77 78 82 private static class LocalArchiveEntry implements Entry { 83 private ZipFile zipFile; 84 85 public LocalArchiveEntry(String fileName) throws IOException { 86 try { 87 zipFile = new ZipFile (fileName); 88 } catch (IOException e) { 89 IOException ioe = new IOException ("Could not open archive file " + fileName); 90 ioe.initCause(e); 91 throw ioe; 92 } 93 } 94 95 98 public InputStream openStream(String resourceName) throws IOException { 99 ZipEntry zipEntry = zipFile.getEntry(resourceName); 100 if (zipEntry == null) 101 return null; 102 return zipFile.getInputStream(zipEntry); 103 } 104 105 108 public String getURL() { 109 return zipFile.getName(); 110 } 111 112 public void close() { 113 try { 114 zipFile.close(); 115 } catch (IOException e) { 116 } 118 } 119 } 120 121 125 private static class LocalDirectoryEntry implements Entry { 126 private String dirName; 127 128 134 public LocalDirectoryEntry(String dirName) throws IOException { 135 this.dirName = dirName; 136 if (!(new File (dirName).isDirectory())) 137 throw new IOException (dirName + " is not a directory"); 138 } 139 140 143 public InputStream openStream(String resourceName) throws IOException { 144 File file = new File (dirName, resourceName); 145 if (!file.exists()) 146 return null; 147 return new BufferedInputStream (new FileInputStream (file)); 148 } 149 150 153 public String getURL() { 154 return dirName; 155 } 156 157 public void close() { 158 } 160 161 } 162 163 168 private static class RemoteArchiveEntry implements Entry { 169 private URL remoteArchiveURL; 170 171 175 public RemoteArchiveEntry(URL remoteArchiveURL) { 176 this.remoteArchiveURL = remoteArchiveURL; 177 } 178 179 182 public InputStream openStream(String resourceName) throws IOException { 183 URL remoteFileURL = new URL ("jar:" + remoteArchiveURL.toString() + 184 "/" + resourceName); 185 try { 186 return remoteFileURL.openStream(); 187 } catch (IOException e) { 188 return null; 189 } 190 } 191 192 195 public String getURL() { 196 return remoteArchiveURL.toString(); 197 } 198 199 public void close() { 200 } 202 203 } 204 205 208 private static class RemoteDirectoryEntry implements Entry { 209 private URL remoteDirURL; 210 211 215 public RemoteDirectoryEntry(URL remoteDirURL) { 216 this.remoteDirURL = remoteDirURL; 217 } 218 219 222 public InputStream openStream(String resourceName) throws IOException { 223 URL remoteFileURL = new URL (remoteDirURL.toString() + resourceName); 224 try { 225 return remoteFileURL.openStream(); 226 } catch (IOException e) { 227 return null; 228 } 229 } 230 231 234 public String getURL() { 235 return remoteDirURL.toString(); 236 } 237 238 public void close() { 239 } 241 } 242 243 private List <Entry > entryList; 245 246 250 public URLClassPath() { 251 this.entryList = new LinkedList <Entry >(); 252 } 253 254 264 public void addURL(String fileName) throws IOException { 265 String protocol = URLClassPath.getURLProtocol(fileName); 266 if (protocol == null) { 267 fileName = "file:" + fileName; 268 protocol = "file"; 269 } 270 271 String fileExtension = URLClassPath.getFileExtension(fileName); 272 boolean isArchive = fileExtension != null && URLClassPath.isArchiveExtension(fileExtension); 273 274 Entry entry; 275 if (protocol.equals("file")) { 276 String localFileName = fileName.substring("file:".length()); 277 278 if (fileName.endsWith("/") || new File (localFileName).isDirectory()) 279 entry = new LocalDirectoryEntry(localFileName); 280 else if (isArchive) 281 entry = new LocalArchiveEntry(localFileName); 282 else 283 throw new IOException ("Classpath entry " + fileName + 284 " is not a directory or archive file"); 285 } else { 286 if (fileName.endsWith("/")) 287 entry = new RemoteDirectoryEntry(new URL (fileName)); 288 else if (isArchive) 289 entry = new RemoteArchiveEntry(new URL (fileName)); 290 else 291 throw new IOException ("Classpath entry " + fileName + 292 " is not a remote directory or archive file"); 293 } 294 295 entryList.add(entry); 296 } 297 298 302 public String getClassPath() { 303 StringBuffer buf = new StringBuffer (); 304 for (Entry entry : entryList) { 305 if (buf.length() > 0) 306 buf.append(File.pathSeparator); 307 buf.append(entry.getURL()); 308 } 309 return buf.toString(); 310 } 311 312 321 private InputStream getInputStreamForResource(String resourceName) throws IOException { 322 325 338 for (Entry entry : entryList) { 339 InputStream in; 340 try { 341 in = entry.openStream(resourceName); 342 if (in != null) { 343 if (URLClassPathRepository.DEBUG) { 344 System.out.println("\t==> found " + resourceName + " in " + entry.getURL()); 345 } 346 return in; 347 } 348 } catch (IOException ignore) { 349 } 351 } 352 if (URLClassPathRepository.DEBUG) { 353 System.out.println("\t==> could not find " + resourceName + " on classpath"); 354 } 355 return null; 356 } 357 private Set <String > classesThatCantBeFound = new HashSet <String >(); 358 366 public JavaClass lookupClass(String className) throws ClassNotFoundException { 367 if (classesThatCantBeFound.contains(className)) { 368 throw new ClassNotFoundException ("Error while looking for class " + 369 className + ": class not found"); 370 } 371 String resourceName = className.replace('.', '/') + ".class"; 372 InputStream in = null; 373 boolean parsedClass = false; 374 375 try { 376 377 in = getInputStreamForResource(resourceName); 378 if (in == null) { 379 classesThatCantBeFound.add(className); 380 throw new ClassNotFoundException ("Error while looking for class " + 381 className + ": class not found"); 382 } 383 384 ClassParser classParser = new ClassParser(in, resourceName); 385 JavaClass javaClass = classParser.parse(); 386 parsedClass = true; 387 388 return javaClass; 389 } catch (IOException e) { 390 classesThatCantBeFound.add(className); 391 throw new ClassNotFoundException ("IOException while looking for class " + 392 className + ": " + e.toString()); 393 } finally { 394 if (in != null && !parsedClass) { 395 try { 396 in.close(); 397 } catch (IOException ignore) { 398 } 400 } 401 } 402 } 403 404 407 public void close() { 408 for (Entry entry : entryList) { 409 entry.close(); 410 } 411 entryList.clear(); 412 } 413 414 419 public static String getURLProtocol(String urlString) { 420 String protocol = null; 421 int firstColon = urlString.indexOf(':'); 422 if (firstColon >= 0) { 423 String specifiedProtocol = urlString.substring(0, firstColon); 424 if (FindBugs.knownURLProtocolSet.contains(specifiedProtocol)) 425 protocol = specifiedProtocol; 426 } 427 return protocol; 428 } 429 430 434 public static String getFileExtension(String fileName) { 435 int lastDot = fileName.lastIndexOf('.'); 436 return (lastDot >= 0) 437 ? fileName.substring(lastDot) 438 : null; 439 } 440 441 448 public static boolean isArchiveExtension(String fileExtension) { 449 return Archive.ARCHIVE_EXTENSION_SET.contains(fileExtension); 450 } 451 } 452 453 | Popular Tags |