/* * @(#)ClassTable.java 1.9 06/11/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */ package components; import jcc.Util; import jcc.Str2ID; import consts.Const; import util.*; import java.util.Enumeration; import java.util.Hashtable; import java.util.Set; import java.util.Vector; /* * The symbol table for classes. * * At any time there is only one classloader for the classes being * processed. The current classloader is maintained by the * ClassTable class. The only way to change the classloader is by calling * ClassTable.setClassLoader(), which happens when '-cl' option is seen. * * Example: btclasses.zip -cl:sys testclasses.zip * * The initial classloader is the boot classloader. The * default parent for a new classloader is the previous classloader. * Classes are searched according to the classloader hierarchy. * Unresolved classes will be searched for in the search path specified * by -classpath. Any classes found will be belong to the classloader * that was in effect when the search path was specified. * * Example: * btclasses.zip -classpath btdep.zip -cl:sys app.jar -classpath appdep.zip */ public class ClassTable { /** * We keep track of classes by hashing them by name when * we read them. They can be looked up using lookupClass, * which will take a classname string as parameter. */ static Vector allClasses = new Vector(); static ClassLoader bootLoader = new ClassLoader("boot", null); static ClassLoader loader = bootLoader; static ClassLoader allLoader = new ClassLoader("all", null); static Hashtable loaders = new Hashtable(); static Hashtable classTable = loader.classes; static String classLoaderNames = ""; static int numClassLoaders = 0; static { loaders.put("boot", bootLoader); // ID 0 loaders.put("all", allLoader); // ID 1 allClasses = new Vector(); } private static boolean primitivesDone = false; /** * Initializes the class table if it hasn't already been initialized. */ public static void initIfNeeded(int verbosity) { if (!primitivesDone) { vm.PrimitiveClassInfo.init(verbosity > 1); primitivesDone = true; } } // Set search path for current classloader public static void setSearchPath(ClassFileFinder searchPath) { loader.setSearchPath(searchPath); } public static void setClassLoader(ClassLoader l) { loader = l; classTable = loader.classes; loaders.put(l.name, l); if (classLoaderNames.length() == 0) { classLoaderNames = l.name; } else { classLoaderNames = classLoaderNames + "," + l.name; } ++numClassLoaders; } public static int getNumClassLoaders() { return numClassLoaders; } public static String getClassLoaderNames() { return classLoaderNames; } public static ClassLoader getClassLoader() { return loader; } public static ClassLoader getClassLoader(String name) { return (ClassLoader)loaders.get(name); } public static boolean enterClass(ClassInfo cinfo, ClassLoader loader) { loader.enterClass(cinfo); String className = cinfo.className; // Make sure a classvector hasn't been created yet. // (used to add, now we just assert that it isn't necessary). if (vm.ClassClass.hasClassVector()){ System.err.println(Localizer.getString( "classtable.class_vector_in_place", className)); return false; } allClasses.add(cinfo); return true; } public static boolean enterClass(ClassInfo cinfo){ if (!(cinfo instanceof vm.ArrayClassInfo)) { return enterClass(cinfo, loader); } else { return enterClass(cinfo, cinfo.loader); } } private static Hashtable sigToPrimitive = new Hashtable(); public static boolean enterPrimitiveClass(vm.PrimitiveClassInfo pci) { boolean success = enterClass(pci, bootLoader); if (success) { sigToPrimitive.put(new Character(pci.signature), pci); } return success; } /* Enter classes associated with a specific classloader. * The classes are not added to 'allClass' like the * other enterClasses() methods do. Also note, this * is not intended for array classes. */ public static boolean enterClasses(Enumeration e, ClassLoader l){ while(e.hasMoreElements()){ ClassInfo c = (ClassInfo)(e.nextElement()); l.enterClass(c); } return true; } public static boolean enterClasses(Enumeration e){ // This is one place where we could restrict user // classloaders from defining java.*, sun.*, etc. // classes while(e.hasMoreElements()){ ClassInfo c = (ClassInfo)(e.nextElement()); if (!enterClass(c)) { return false; } } return true; } public static vm.PrimitiveClassInfo lookupPrimitiveClass(char sig){ return (vm.PrimitiveClassInfo)sigToPrimitive.get(new Character(sig)); } public static ClassInfo lookupClass(String key){ return loader.lookupClass(key); } public static ClassInfo lookupClass(String key, ClassLoader l){ return l.lookupClass(key); } public static int size(){ return allClasses.size(); } public static Enumeration elements(){ return allClasses.elements(); } public static ClassInfo[] allClasses() { Enumeration classEnum = elements(); int nclasses = size(); ClassInfo ary[] = new ClassInfo[ nclasses ]; for (int i= 0; i < nclasses; i++){ ary[i] = (ClassInfo) classEnum.nextElement(); } return ary; } }