001 package org.extendj.ast; 002 003 import java.util.HashSet; 004 import java.io.File; 005 import java.util.Set; 006 import java.util.Collections; 007 import java.util.Collection; 008 import java.util.ArrayList; 009 import beaver.*; 010 import java.util.*; 011 import java.io.ByteArrayOutputStream; 012 import java.io.PrintStream; 013 import java.lang.reflect.InvocationTargetException; 014 import java.lang.reflect.Method; 015 import org.jastadd.util.*; 016 import java.util.zip.*; 017 import java.io.*; 018 import org.jastadd.util.PrettyPrintable; 019 import org.jastadd.util.PrettyPrinter; 020 import java.io.FileNotFoundException; 021 import java.io.BufferedInputStream; 022 import java.io.DataInputStream; 023 /** 024 * @ast class 025 * @aspect PathPart 026 * @declaredat /home/jesper/git/extendj/java4/frontend/PathPart.jadd:510 027 */ 028 public class JarFilePath extends PathPart { 029 030 private Collection<String> packageIndex = null; 031 032 033 private final ZipFile jar; 034 035 036 private final String jarPath; 037 038 039 040 public JarFilePath(String jarPath) throws IOException { 041 super(false); 042 this.jar = new ZipFile(jarPath); 043 this.jarPath = jarPath; 044 } 045 046 047 048 public JarFilePath(File jarFile) throws IOException { 049 super(false); 050 this.jar = new ZipFile(jarFile); 051 this.jarPath = jarFile.getPath(); 052 } 053 054 055 056 @Override 057 public String getPath() { 058 return jarPath; 059 } 060 061 062 063 private static void scanJar(ZipFile jar, Collection<String> packages, 064 String fileSuffix) { 065 // Add all zip entries to a set so that we can quickly check if the Jar 066 // contains a given class 067 for (Enumeration entries = jar.entries(); entries.hasMoreElements(); ) { 068 ZipEntry entry = (ZipEntry) entries.nextElement(); 069 String path = entry.getName(); 070 if (path.endsWith(fileSuffix)) { 071 addPackages(packages, path); 072 } 073 } 074 } 075 076 077 078 private static void addPackages(Collection<String> packages, String path) { 079 String name = path.replace('/', '.'); 080 int index = path.length(); 081 do { 082 index = path.lastIndexOf('/', index-1); 083 } while (index >= 0 && packages.add(name.substring(0, index))); 084 } 085 086 087 088 /** 089 * Caches the package index from the Jar file so that subsequent calls to 090 * this method are quicker. 091 */ 092 @Override 093 public boolean hasPackage(String name) { 094 synchronized (this) { 095 if (packageIndex == null) { 096 packageIndex = new HashSet<String>(); 097 scanJar(jar, packageIndex, fileSuffix); 098 } 099 } 100 return packageIndex.contains(name); 101 } 102 103 104 105 @Override 106 public ClassSource findSource(String name) { 107 // ZipFiles always use '/' as separator 108 String jarName = name.replace('.', '/') + fileSuffix; 109 ZipEntry entry = jar.getEntry(jarName); 110 if (entry != null) { 111 return new JarClassSource(this, jar, entry, jarPath); 112 } else { 113 return ClassSource.NONE; 114 } 115 } 116 117 118 119 @Override 120 public String toString() { 121 return "jar:" + jarPath; 122 } 123 124 125 }