00001 package edu.ksu.cis.bandera.jjjc.symboltable;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import java.io.*;
00036 import java.util.*;
00037 import java.util.zip.*;
00038 import edu.ksu.cis.bandera.jjjc.util.Util;
00039 import edu.ksu.cis.bandera.jjjc.exception.*;
00040
00041 public class Package implements Named {
00042 private static Vector visitedPaths = new Vector();
00043 private static Hashtable packages;
00044 private static Hashtable foundTypes;
00045 private static HashSet notFoundTypes;
00046
00047 private Name name;
00048 private Vector paths = new Vector();
00049 private Hashtable types = new Hashtable();
00050
00051
00052
00053
00054 protected Package(Name name) throws InvalidNameException {
00055 boolean validName = true;
00056
00057
00058 Package p = (Package) packages.get(name.getSuperName());
00059
00060 this.name = name;
00061 }
00062
00063
00064
00065
00066 public void addType(ClassOrInterfaceType type) {
00067 types.put(new Name(type.getName().getLastIdentifier()), type);
00068 foundTypes.put(type.getName(), type);
00069 }
00070
00071
00072
00073
00074
00075 public boolean equals(Object obj) {
00076 if (obj == null) return false;
00077 else if (!(obj instanceof Package)) return false;
00078 else return this.getName().equals(((Package)obj).getName());
00079 }
00080
00081
00082
00083
00084
00085
00086 private static boolean exists(String path, String filename) {
00087 File dir = new File(path);
00088 String[] files = dir.list();
00089
00090 for (int i = 0; i < files.length; i++) {
00091 if (files[i].equals(filename)) {
00092 return true;
00093 }
00094 }
00095 return false;
00096 }
00097
00098
00099
00100
00101
00102 public static ClassOrInterfaceType getClassOrInterfaceType(Name name) throws ClassOrInterfaceTypeNotFoundException,
00103 InvalidNameException {
00104 if (foundTypes.get(name) != null) return (ClassOrInterfaceType) foundTypes.get(name);
00105 if (notFoundTypes.contains(name)) throw new ClassOrInterfaceTypeNotFoundException("Could not load type '" + name.toString() + "'");
00106 Name packageName = name.isSimpleName() ? new Name("") : name.getSuperName();
00107 Name className = new Name(name.getLastIdentifier());
00108
00109 if (Package.hasPackage(name))
00110 throw new InvalidNameException("Could not have class named " + className.toString() + " in package "
00111 + packageName.toString() + ", because there is a package named " + name);
00112
00113 Package p = null;
00114 String path = null;
00115 boolean isFound = false;
00116 if (packages.get(packageName) == null) {
00117 try {
00118 Class.forName(name.toString());
00119 isFound = true;
00120 p = getPackage(packageName);
00121 } catch (Exception e) {}
00122 } else {
00123 p = (Package) packages.get(packageName);
00124
00125 if (p.types.get(className) != null)
00126 return (ClassOrInterfaceType) p.types.get(className);
00127
00128
00129 for (int i = 0; i < p.paths.size(); i++) {
00130 if (exists((String) p.paths.elementAt(i), className.toString() + ".java")) {
00131 isFound = true;
00132 path = (String) p.paths.elementAt(i) + File.separator + className.toString() + ".java";
00133 break;
00134 }
00135 }
00136
00137 if (!isFound) {
00138 try {
00139 Class c = Class.forName(name.toString());
00140 if (c.getName().equals(packageName + "." + className)) {
00141 isFound = true;
00142 }
00143 } catch (Throwable e) {}
00144 }
00145 }
00146
00147 if (isFound) {
00148 ClassOrInterfaceType c = new ClassOrInterfaceType(p, className, path);
00149 p.addType(c);
00150 return c;
00151 } else {
00152 notFoundTypes.add(name);
00153 throw new ClassOrInterfaceTypeNotFoundException("Could not load type '" + name.toString() + "'");
00154 }
00155 }
00156
00157
00158
00159
00160 public Name getName() {
00161 return name;
00162 }
00163
00164
00165
00166
00167
00168 public static Package getPackage(Name name) throws InvalidNameException {
00169 if (packages.get(name) == null)
00170 packages.put(name, new Package(name));
00171
00172 return (Package) packages.get(name);
00173 }
00174
00175
00176
00177
00178 public static Hashtable getPackages() {
00179 return packages;
00180 }
00181
00182
00183
00184
00185 public Enumeration getPaths() {
00186 return paths.elements();
00187 }
00188
00189
00190
00191
00192 public Enumeration getTypes() {
00193 return types.elements();
00194 }
00195
00196
00197
00198
00199
00200 public static boolean hasPackage(Name name) {
00201 return (packages.get(name) != null);
00202 }
00203
00204
00205
00206
00207
00208 public boolean hasType(Name name) {
00209 try {
00210 getClassOrInterfaceType(new Name(this.name, name));
00211 return true;
00212 } catch (CompilerException e) {
00213 return false;
00214 }
00215 }
00216
00217
00218
00219
00220
00221 protected static void registerPackages(String name, String path) throws InvalidNameException {
00222 if (visitedPaths.contains(path)) {
00223 return;
00224 }
00225 visitedPaths.addElement(path);
00226 Name n = new Name(name);
00227 Package p;
00228 if (packages.get(n) == null) {
00229 p = new Package(n);
00230 packages.put(n, p);
00231 } else p = (Package) packages.get(n);
00232
00233 p.paths.addElement(path);
00234
00235 String[] files = new File(path).list();
00236
00237 if (files != null) {
00238 for (int i = 0; i < files.length; i++) {
00239 File file = new File(path, files[i]);
00240 if (file.isDirectory())
00241 try {
00242 registerPackages(name + "." + files[i], file.getCanonicalPath());
00243 } catch (Exception e) {}
00244 }
00245 }
00246 }
00247
00248
00249
00250
00251 public static void setClassPath(String classPath) throws CompilerException {
00252 packages = new Hashtable();
00253 foundTypes = new Hashtable();
00254 notFoundTypes = new HashSet();
00255 visitedPaths = new Vector();
00256 String[] paths = Util.splitString(classPath, File.pathSeparator);
00257 for (int i = 0; i < paths.length; i++) {
00258 String path = paths[i];
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 try {
00283 registerPackages("", new File(path).getCanonicalPath());
00284 } catch (Exception e) {
00285 throw new CompilerException("Failed to register packages from class path");
00286 }
00287
00288 }
00289 try {
00290 if (packages.get(new Name("")) == null) {
00291 Package p = new Package(new Name(""));
00292 packages.put(p.getName(), p);
00293 }
00294 } catch (InvalidNameException e) {}
00295 }
00296
00297
00298
00299
00300 public String toString() {
00301 return name.toString();
00302 }
00303 }