001: /*
002: * @(#)ClassTable.java 1.9 06/11/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package components;
029:
030: import jcc.Util;
031: import jcc.Str2ID;
032: import consts.Const;
033: import util.*;
034:
035: import java.util.Enumeration;
036: import java.util.Hashtable;
037: import java.util.Set;
038: import java.util.Vector;
039:
040: /*
041: * The symbol table for classes.
042: *
043: * At any time there is only one classloader for the classes being
044: * processed. The current classloader is maintained by the
045: * ClassTable class. The only way to change the classloader is by calling
046: * ClassTable.setClassLoader(), which happens when '-cl' option is seen.
047: *
048: * Example: btclasses.zip -cl:sys testclasses.zip
049: *
050: * The initial classloader is the boot classloader. The
051: * default parent for a new classloader is the previous classloader.
052: * Classes are searched according to the classloader hierarchy.
053: * Unresolved classes will be searched for in the search path specified
054: * by -classpath. Any classes found will be belong to the classloader
055: * that was in effect when the search path was specified.
056: *
057: * Example:
058: * btclasses.zip -classpath btdep.zip -cl:sys app.jar -classpath appdep.zip
059: */
060:
061: public class ClassTable {
062:
063: /**
064: * We keep track of classes by hashing them by name when
065: * we read them. They can be looked up using lookupClass,
066: * which will take a classname string as parameter.
067: */
068: static Vector allClasses = new Vector();
069: static ClassLoader bootLoader = new ClassLoader("boot", null);
070: static ClassLoader loader = bootLoader;
071: static Hashtable loaders = new Hashtable();
072: static Hashtable classTable = loader.classes;
073: static String classLoaderNames = "";
074: static int numClassLoaders = 0;
075:
076: static {
077: loaders.put("boot", bootLoader); // ID 0
078: allClasses = new Vector();
079: }
080:
081: private static boolean primitivesDone = false;
082:
083: public static void init(int verbosity) {
084: if (!primitivesDone) {
085: vm.PrimitiveClassInfo.init(verbosity > 1);
086: primitivesDone = true;
087: }
088: }
089:
090: // Set search path for current classloader
091: public static void setSearchPath(ClassFileFinder searchPath) {
092: loader.setSearchPath(searchPath);
093: }
094:
095: public static void setClassLoader(ClassLoader l) {
096: loader = l;
097: classTable = loader.classes;
098: loaders.put(l.name, l);
099: if (classLoaderNames.length() == 0) {
100: classLoaderNames = l.name;
101: } else {
102: classLoaderNames = classLoaderNames + "," + l.name;
103: }
104: ++numClassLoaders;
105: }
106:
107: public static int getNumClassLoaders() {
108: return numClassLoaders;
109: }
110:
111: public static String getClassLoaderNames() {
112: return classLoaderNames;
113: }
114:
115: public static ClassLoader getClassLoader() {
116: return loader;
117: }
118:
119: public static ClassLoader getClassLoader(String name) {
120: return (ClassLoader) loaders.get(name);
121: }
122:
123: public static boolean enterClass(ClassInfo c, ClassLoader l) {
124: l.enterClass(c);
125: String className = c.className;
126: // Make sure a classvector hasn't been created yet.
127: // (used to add, now we just assert that it isn't necessary).
128: if (vm.ClassClass.hasClassVector()) {
129: System.err.println(Localizer.getString(
130: "classtable.class_vector_in_place", className));
131: return false;
132: }
133: allClasses.add(c);
134: return true;
135: }
136:
137: public static boolean enterClass(ClassInfo c) {
138: if (!(c instanceof vm.ArrayClassInfo)) {
139: return enterClass(c, loader);
140: } else {
141: return enterClass(c, c.loader);
142: }
143: }
144:
145: private static Hashtable sigToPrimitive = new Hashtable();
146:
147: public static boolean enterPrimitiveClass(vm.PrimitiveClassInfo pci) {
148: boolean success = enterClass(pci, bootLoader);
149: if (success) {
150: sigToPrimitive.put(new Character(pci.signature), pci);
151: }
152: return success;
153: }
154:
155: /* Enter classes associated with a specific classloader.
156: * The classes are not added to 'allClass' like the
157: * other enterClasses() methods do. Also note, this
158: * is not intended for array classes.
159: */
160: public static boolean enterClasses(Enumeration e, ClassLoader l) {
161: while (e.hasMoreElements()) {
162: ClassInfo c = (ClassInfo) (e.nextElement());
163: l.enterClass(c);
164: }
165: return true;
166: }
167:
168: public static boolean enterClasses(Enumeration e) {
169: // This is one place where we could restrict user
170: // classloaders from defining java.*, sun.*, etc.
171: // classes
172: while (e.hasMoreElements()) {
173: ClassInfo c = (ClassInfo) (e.nextElement());
174: if (!enterClass(c)) {
175: return false;
176: }
177: }
178: return true;
179: }
180:
181: public static vm.PrimitiveClassInfo lookupPrimitiveClass(char sig) {
182: return (vm.PrimitiveClassInfo) sigToPrimitive
183: .get(new Character(sig));
184: }
185:
186: public static ClassInfo lookupClass(String key) {
187: return loader.lookupClass(key);
188: }
189:
190: public static ClassInfo lookupClass(String key, ClassLoader l) {
191: return l.lookupClass(key);
192: }
193:
194: public static int size() {
195: return allClasses.size();
196: }
197:
198: public static Enumeration elements() {
199: return allClasses.elements();
200: }
201:
202: public static ClassInfo[] allClasses() {
203: Enumeration classEnum = elements();
204: int nclasses = size();
205: ClassInfo ary[] = new ClassInfo[nclasses];
206: for (int i = 0; i < nclasses; i++) {
207: ary[i] = (ClassInfo) classEnum.nextElement();
208: }
209: return ary;
210: }
211:
212: }
|