/************************************************* * * = PACKAGE * JACE.ServiceConfigurator * * = FILENAME * ClassReader.java * *@author Everett Anderson * *@see JACE.ServiceConfigurator *@see JACE.ServiceConfigurator.ServiceLoader * *************************************************/ package JACE.ServiceConfigurator; import JACE.OS.*; import java.io.*; import java.util.*; /** *
*

TITLE
* Given a classfile name, this determines the qualified class name * of what's inside (pacakage and class name together). It is necessary * when users want to dynamically load classes, but don't provide the * full name in svc.conf. */ public class ClassReader { // Types found in classfiles public static final byte CONSTANT_Class = 7; public static final byte CONSTANT_Fieldref = 9; public static final byte CONSTANT_Methodref = 10; public static final byte CONSTANT_InterfaceMethodref = 11; public static final byte CONSTANT_String = 8; public static final byte CONSTANT_Integer = 3; public static final byte CONSTANT_Float = 4; public static final byte CONSTANT_Long = 5; public static final byte CONSTANT_Double = 6; public static final byte CONSTANT_NameAndType = 12; public static final byte CONSTANT_Utf8 = 1; /** Returns a string that is the qualified class name of the * given file. It returns null if there are any problems. * *@param fileName File to examine * *@return String that's the qualified class name of the * given file (null on error) */ public static String getClassName(String fileName) { try { // Open the .class file FileInputStream fis = new FileInputStream(fileName); DataInputStream dis = new DataInputStream(fis); // Skip magic number and version numbers dis.skipBytes(8); // Find out how many entries are in the constant pool table int count = dis.readUnsignedShort(); // Hash table to hold the text entries (possibilities for // the class name) Hashtable ht = new Hashtable(); // Vector that holds the index of the class name for each // class record (the vector is indexed by placement in the // table) Vector vt = new Vector(count); Integer noValue = new Integer(-1); int type; // Scan through all the entries for (int i = 1; i < count; i++) { // Read what type of entry this is type = dis.readUnsignedByte(); switch (type) { case CONSTANT_Class: // Save the index of the class name vt.addElement(new Integer(dis.readUnsignedShort())); break; case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: case CONSTANT_Integer: case CONSTANT_Float: case CONSTANT_NameAndType: // Skip the data vt.addElement(noValue); dis.skipBytes(4); break; case CONSTANT_String: // Skip the data vt.addElement(noValue); dis.skipBytes(2); break; case CONSTANT_Long: case CONSTANT_Double: // Skip the data vt.addElement(noValue); dis.skipBytes(8); // These take up two spots in the table i++; break; case CONSTANT_Utf8: vt.addElement(noValue); // Save the text in the hash table ht.put(new Integer(i), new String(dis.readUTF())); break; default: ACE.DEBUG("Unknown type: " + type); break; } } // Skip the access flags dis.skipBytes(2); // Get index in table of this class int classIdx = dis.readUnsignedShort(); // Get index in the table of the name of this class Integer idx = (Integer)vt.elementAt(classIdx - 1); // Put the result in period separated notation String result = new String(((String)ht.get(idx)).replace('/', '.')); return result; } catch (IOException e) { ACE.ERROR("" + e); return null; } } }