home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 July / Chip_1998-07_cd.bin / zkuste / JBuilder / BDK / Win / bdk_sep97.exe / _SETUP.1 / ClassFile.java < prev    next >
Encoding:
Java Source  |  1997-09-10  |  10.9 KB  |  430 lines

  1. /*
  2.  *
  3.  * @(#) ClassFile.java 1.5@(#)
  4.  *
  5.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  6.  * 
  7.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  8.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  9.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  10.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  11.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  12.  * THIS SOFTWARE OR ITS DERIVATIVES.
  13.  * 
  14.  */
  15.  
  16. /**
  17.  * <p>
  18.  * sunw.demo.classfile.ClassFile
  19.  * </p> 
  20.  *
  21.  * @version 1.0
  22.  * @author Laurence P. G. Cable
  23.  */
  24.  
  25. package sunw.demo.classfile;
  26.  
  27. import java.io.DataOutputStream;
  28. import java.io.IOException;
  29. import java.io.OutputStream;
  30.  
  31. import java.util.Vector;
  32. import java.util.Hashtable;
  33.  
  34. /**
  35.  * <p>
  36.  * The ClassFile class is designed to provide lightweight, minimal support
  37.  * for the runtime construction of Java VM ClassFile's, or Class
  38.  * implementations.
  39.  * </p>
  40.  * <p>
  41.  * The ClassFile provides API's to construct an in-core description of a
  42.  * Java class implementation, and subsequently write that description to 
  43.  * a stream which may then be either loaded into the VM via a ClassLoader
  44.  * or written to some persistent store.
  45.  * </p>
  46.  * <p>
  47.  * It should be noted that the ClassFile provide little or no validation of
  48.  * the Class it describes during the construction of that description, and
  49.  * therefore users of this class and package should be familiar with the 
  50.  * contents of the Java VM Specification published by Addison-Wesley.
  51.  * </p>
  52.  */
  53.  
  54. final class ClassFile {
  55.  
  56.     /**
  57.      * <p> the magic number for Java VM class files. </p>
  58.      */
  59.  
  60.     final private static int MAGIC = 0xcafebabe;
  61.  
  62.     /**
  63.      * <p> the major and minor version numbers for Java VM class files. </p>
  64.      */
  65.  
  66.     final private static short MAJOR = 45;
  67.     final private static short MINOR = 3;
  68.     
  69.     /**
  70.      * <p> the access flags constants for Java VM class files. </p>
  71.      */
  72.  
  73.     final static         short ACC_PUBLIC    = 0x0001;
  74.     final static         short ACC_FINAL     = 0x0010;
  75.     final static         short ACC_SUPER     = 0x0020;
  76.     final static         short ACC_INTERFACE = 0x0200;
  77.     final static         short ACC_ABSTRACT  = 0x0400;
  78.  
  79.     /*
  80.      * inst vars represent the format of the classfile itself.
  81.      */
  82.  
  83.     private Vector        constantPool = new Vector(1);
  84.     private Hashtable        constantHash = new Hashtable();
  85.  
  86.     private short        accessFlags  = (short)(ACC_PUBLIC | ACC_SUPER);
  87.  
  88.     private ClassConstant    thisClass;
  89.     private ClassConstant       superClass;
  90.  
  91.     private Vector          interfaces;
  92.     private Vector        fields;
  93.     private Vector        methods;
  94.     private Vector        attributes;
  95.  
  96.     /**
  97.      * @return are we debuging (used to print audit trail).
  98.      */
  99.  
  100.     static boolean debug() { return false; }
  101.  
  102.     /**
  103.      * <p> Construct a new ClassFile object. </p>
  104.      *
  105.      * @param tClass    name of "this" class
  106.      *
  107.      * @param sClass    name of superclass
  108.      *
  109.      */
  110.  
  111.     ClassFile(String tClass, String sClass) {
  112.         thisClass  = addClassConstant(tClass);
  113.         superClass = addClassConstant(sClass);
  114.     }
  115.  
  116.     /**
  117.      * <p> Write the constant pool to the stream </p>
  118.      *
  119.      * @param dos the stream to write to.
  120.      */
  121.  
  122.     private void writeConstantPool(DataOutputStream dos) throws IOException {
  123.  
  124.     if (debug()) System.err.println("write constant pool: " + constantPool.size());
  125.  
  126.         dos.writeShort(constantPool.size() + 1); // for index zero
  127.  
  128.         for (int i = 0; i < constantPool.size(); i++) {
  129.             ((ConstantPoolEntry)constantPool.elementAt(i)).write(dos);
  130.         }
  131.     }
  132.  
  133.     /**
  134.      * <p> Write the list of interfaces to the stream </p>
  135.      *
  136.      * @param dos the stream to write to.
  137.      */
  138.  
  139.     private void writeInterfaces(DataOutputStream dos) throws IOException {
  140.         if (interfaces != null) {
  141.         if (debug()) System.err.println("write interfaces: " + interfaces.size());
  142.             dos.writeShort(interfaces.size());
  143.  
  144.             for (int i = 0; i < interfaces.size(); i++) {
  145.                 dos.writeShort(
  146.             ((ConstantPoolEntry)interfaces.elementAt(i)).getConstantPoolIndex()
  147.         );
  148.             }
  149.         } else dos.writeShort(0);
  150.     }
  151.  
  152.     /**
  153.      * <p> Write the list of Fields defs to the stream </p>
  154.      *
  155.      * @param dos the stream to write to.
  156.      */
  157.  
  158.     private void writeFields(DataOutputStream dos) throws IOException {
  159.         if (fields != null) {
  160.         if (debug()) System.err.println("write fields: " + fields.size());
  161.  
  162.         dos.writeShort(fields.size());
  163.  
  164.             for (int i = 0; i < fields.size(); i++) {
  165.                 ((FieldDesc)fields.elementAt(i)).write(dos);
  166.             }
  167.         } else dos.writeShort(0);
  168.     }
  169.  
  170.     /**
  171.      * <p> Write the list of Method defs to the stream. </p>
  172.      *
  173.      * @param dos the stream to write to.
  174.      */
  175.  
  176.     private void writeMethods(DataOutputStream dos) throws IOException {
  177.         if (methods != null) {
  178.         if (debug()) System.err.println("write methods: " + methods.size());
  179.  
  180.             dos.writeShort(methods.size());
  181.  
  182.             for (int i = 0; i < methods.size(); i++) {
  183.                 ((MethodDesc)methods.elementAt(i)).write(dos);
  184.             }
  185.         } else dos.writeShort(0);
  186.  
  187.     }
  188.  
  189.     /**
  190.      * <p> Write the list of Attributes to the stream </p>
  191.      *
  192.      * @param dos the stream to write to.
  193.      */
  194.  
  195.     private void writeAttributes(DataOutputStream dos) throws IOException {
  196.         if (attributes != null) {
  197.         if (debug()) System.err.println("write attributes: " + attributes.size());
  198.  
  199.             dos.writeShort(attributes.size());
  200.  
  201.             for (int i = 0; i < attributes.size(); i++) {
  202.                 ((Attribute)attributes.elementAt(i)).write(dos);
  203.             }
  204.         } else dos.writeShort(0);
  205.     }
  206.  
  207.     /**
  208.      * <p> Write the ClassFile to the Stream </p>
  209.      *
  210.      * @param os the stream to write to.
  211.      */
  212.  
  213.     public synchronized void write(OutputStream os) throws IOException {
  214.         DataOutputStream dos = new DataOutputStream(os);
  215.  
  216.         try {
  217.             dos.writeInt(MAGIC);
  218.  
  219.             dos.writeShort(MINOR);
  220.             dos.writeShort(MAJOR);
  221.  
  222.             writeConstantPool(dos);
  223.  
  224.         if (debug()) System.err.println("access: " + accessFlags);
  225.  
  226.             dos.writeShort(accessFlags);        
  227.  
  228.             dos.writeShort(thisClass.getConstantPoolIndex());
  229.             dos.writeShort(superClass.getConstantPoolIndex());
  230.  
  231.             writeInterfaces(dos);
  232.  
  233.             writeFields(dos);
  234.  
  235.             writeMethods(dos);
  236.  
  237.             writeAttributes(dos);
  238.  
  239.             dos.close(); // all done!
  240.         } catch (IOException ioe) {
  241.         System.err.println("Bad IO");
  242.         } catch (Exception e) {
  243.             System.err.println("Oops");
  244.         }
  245.     }
  246.  
  247.     /**
  248.      * <p> Add an entry to the Constant Pool. </p>
  249.      *
  250.      * @param cpe the new constant pool entry
  251.      *
  252.      * @return the index of the new entry in the pool
  253.      */
  254.  
  255.     public synchronized short addConstantPoolEntry(ConstantPoolEntry cpe) {
  256.  
  257.     ConstantPoolEntry old = (ConstantPoolEntry)constantHash.get(cpe);
  258.     if (old != null) {
  259.         return old.getConstantPoolIndex();
  260.     }
  261.     constantHash.put(cpe,cpe);
  262.  
  263.     constantPool.addElement(cpe);
  264.  
  265.     return (short)constantPool.size();
  266.     }
  267.  
  268.     /**
  269.      * @return the current value of the accessFlags.
  270.      */
  271.  
  272.     public synchronized short getAccessFlags() { return accessFlags; }
  273.  
  274.     /**
  275.      * <p> modify the value of the Class File's access flags </p>
  276.      *
  277.      * @param newf the new flag values. [NOT VALIDATED]
  278.      */
  279.  
  280.     public synchronized void setAccessFlags(short newf) {
  281.  
  282.     // TODO - verify new flag combination.
  283.  
  284.     accessFlags = newf;
  285.     }
  286.  
  287.     /**
  288.      * @param newMethod the method desc to add to the class file.
  289.      */
  290.  
  291.     public synchronized void addMethodDesc(MethodDesc newMethod) {
  292.         if (methods == null) methods = new Vector(1);
  293.  
  294.         methods.addElement(newMethod);
  295.     }
  296.  
  297.     /**
  298.      * @param newField the field desc to add to the class file.
  299.      */
  300.  
  301.     public synchronized void addFieldDesc(FieldDesc newField) {
  302.     if (fields == null) fields = new Vector(1);
  303.  
  304.     fields.addElement(newField);
  305.     }
  306.  
  307.     /**
  308.      * @param sConstant add a CONSTANT_STRING to the ClassFile.
  309.      * 
  310.      * @param sConstant the string value to add.
  311.      * 
  312.      * @return The new StringConstant
  313.      */
  314.  
  315.     public StringConstant addStringConstant(String sConstant) {
  316.     UTF8Constant c = addUTF8Constant(sConstant);
  317.     StringConstant s = new StringConstant(c, this);
  318.     return s;
  319.     }
  320.  
  321.     /**
  322.      * <p> Add a new CONSTANT_INTEGER to the Constant Pool </p>
  323.      *
  324.      * @param iConstant the integer value to add.
  325.      * 
  326.      * @return the new IntegerConstant.
  327.      */
  328.  
  329.     public IntegerConstant addIntegerConstant(int iConstant) {
  330.     return new IntegerConstant(iConstant, this);
  331.     }
  332.  
  333.     /**
  334.      * <p> Add a new UTF8_CONSTANT to the constant pool </p>
  335.      *
  336.      * @param sConstant the string to add.
  337.      *
  338.      * @return the new UUTF8Constant
  339.      */
  340.  
  341.     public UTF8Constant addUTF8Constant(String sConstant) {
  342.     return new UTF8Constant(sConstant, this);
  343.     }
  344.  
  345.     /**
  346.      * <p> add a new CONSTANT_CLASS to the Constant Pool </p>
  347.      *
  348.      * @param classConstant the name of the class to add!!
  349.  
  350.      *
  351.      * @return the newly ClassConstant
  352.      */
  353.  
  354.     public ClassConstant addClassConstant(String classConstant) {
  355.     return new ClassConstant(classConstant, this);
  356.     }
  357.  
  358.     /**
  359.      * <p> add a CONSTANT_METHOD to the constant pool </p>
  360.      *
  361.      * @param cName the name of the defining class
  362.      * @param mName the method name
  363.      * @param tName the fully qualified type descriptor for the method
  364.      *
  365.      * @return the new created CONSTANT_METHOD
  366.      */
  367.  
  368.     public MethodConstant addMethodConstant(String cName, String mName, String tName) {
  369.     return new MethodConstant(cName, mName, tName, this);
  370.     }
  371.  
  372.     /**
  373.      *
  374.      *
  375.      * @param cName the name of the defining class
  376.      * @param fName the name of the field
  377.      * @param tName the fully qualified type descriptor of the field
  378.      *
  379.      * @return the new created CONSTANT_FIELD
  380.      */
  381.  
  382.     public FieldConstant addFieldConstant(String cName, String fName, String tName) {
  383.     return new FieldConstant(cName, fName, tName, this);
  384.     }
  385.  
  386.     /**
  387.      * <p> add the name of an interface this class implements to the constant pool </p>
  388.      * 
  389.      * @param iName the name of the interface
  390.      */
  391.  
  392.     public void addInterface(String iName) {
  393.     if (interfaces == null) interfaces = new Vector(1);
  394.  
  395.     interfaces.addElement((Object)addClassConstant(iName));
  396.     }
  397.  
  398.     /**
  399.      * <p>
  400.      * convenience routine to take a type name and map it to the internal form.
  401.      * java.lang.Object -> java/lang/Object
  402.      * </p>
  403.      *
  404.      * @param str the string to map
  405.      *
  406.      * @return the mapped string value.
  407.      */
  408.  
  409.     public static String fullyQualifiedForm(String str) {
  410.     return str.replace('.', '/');
  411.     }
  412.  
  413.  
  414.     /**
  415.      * <p>
  416.      * convenience routine to construct type descriptors from fully
  417.      * qualified names, e.g: java.lang.Object => Ljava/lang/Object;
  418.      * </p>
  419.      *
  420.      * @param str name of a java "type"
  421.      *
  422.      * @return the class descriptor.
  423.      */
  424.  
  425.     public static String fieldType(String str) {
  426.     return "L" + ClassFile.fullyQualifiedForm(str) + ";";
  427.     }
  428.  
  429. }
  430.