Home | History | Annotate | Download | only in data
      1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
      2  *
      3  * This program and the accompanying materials are made available under
      4  * the terms of the Common Public License v1.0 which accompanies this distribution,
      5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
      6  *
      7  * $Id: ClassDescriptor.java,v 1.1.1.1 2004/05/09 16:57:30 vlad_r Exp $
      8  */
      9 package com.vladium.emma.data;
     10 
     11 import java.io.DataInput;
     12 import java.io.DataOutput;
     13 import java.io.IOException;
     14 import java.io.Serializable;
     15 
     16 import com.vladium.util.IConstants;
     17 import com.vladium.util.asserts.$assert;
     18 
     19 // ----------------------------------------------------------------------------
     20 /**
     21  * @author Vlad Roubtsov, (C) 2003
     22  */
     23 public
     24 final class ClassDescriptor implements IConstants, Serializable
     25 {
     26     // public: ................................................................
     27 
     28 
     29     public ClassDescriptor (final String packageVMName, final String name, final long stamp,
     30                             final String srcFileName,
     31                             final MethodDescriptor [] methods)
     32     {
     33         if (packageVMName == null)
     34             throw new IllegalArgumentException ("null input: packageVMName");
     35         if (name == null)
     36             throw new IllegalArgumentException ("null input: name");
     37         if (methods == null)
     38             throw new IllegalArgumentException ("null input: methods");
     39 
     40         if ($assert.ENABLED)
     41         {
     42             for (int m = 0; m < methods.length; ++ m)
     43             {
     44                 $assert.ASSERT (methods [m] != null, "methods [" + m + "] = null (length = " + methods.length + ")");
     45             }
     46         }
     47 
     48         m_packageVMName = packageVMName;
     49         m_name = name;
     50         m_stamp = stamp;
     51         m_srcFileName = srcFileName;
     52         m_methods = methods; // TODO: defensive copy?
     53 
     54         boolean completeLineNumberInfo = true;
     55         for (int m = 0; m < m_methods.length; ++ m)
     56         {
     57             final MethodDescriptor method = methods [m];
     58 
     59             if (((method.getStatus () & IMetadataConstants.METHOD_NO_BLOCK_DATA) == 0) && ! m_methods [m].hasLineNumberInfo ())
     60             {
     61                 completeLineNumberInfo = false;
     62                 break;
     63             }
     64         }
     65 
     66         m_hasCompleteLineNumberInfo = completeLineNumberInfo;
     67     }
     68 
     69 
     70     // equality is defined based on <m_packageVMName, m_name> only (m_stamp not mixed in by design):
     71 
     72     public final boolean equals (final Object rhs)
     73     {
     74         if (! (rhs instanceof ClassDescriptor)) return false;
     75 
     76         final ClassDescriptor _rhs = (ClassDescriptor) rhs;
     77 
     78         if (hashCode () != _rhs.hashCode ()) return false;
     79 
     80         if (! m_name.equals (_rhs.m_name)) return false;
     81         if (! m_packageVMName.equals (_rhs.m_packageVMName)) return false;
     82 
     83         return true;
     84     }
     85 
     86     public final int hashCode ()
     87     {
     88         if (m_hash == 0)
     89         {
     90             final int hash = m_name.hashCode () + 16661 * m_packageVMName.hashCode ();
     91             m_hash = hash;
     92 
     93             return hash;
     94         }
     95 
     96         return m_hash;
     97     }
     98 
     99 
    100     public final String getPackageVMName ()
    101     {
    102         return m_packageVMName;
    103     }
    104 
    105     public final String getName ()
    106     {
    107         return m_name;
    108     }
    109 
    110     public final long getStamp ()
    111     {
    112         return m_stamp;
    113     }
    114 
    115     public final String getClassVMName ()
    116     {
    117         // TODO: use Descriptors API?
    118         if (m_packageVMName.length () == 0)
    119             return m_name;
    120         else
    121             return new StringBuffer (m_packageVMName).append ("/").append (m_name).toString ();
    122     }
    123 
    124     public final String getSrcFileName ()
    125     {
    126         return m_srcFileName;
    127     }
    128 
    129     public final MethodDescriptor [] getMethods ()
    130     {
    131         return m_methods; // no defensive copy
    132     }
    133 
    134     public final boolean hasSrcFileInfo ()
    135     {
    136         return m_srcFileName != null;
    137     }
    138 
    139     public final boolean hasCompleteLineNumberInfo ()
    140     {
    141         return m_hasCompleteLineNumberInfo;
    142     }
    143 
    144 
    145     public String toString ()
    146     {
    147         return toString ("");
    148     }
    149 
    150     public String toString (final String indent)
    151     {
    152         StringBuffer s = new StringBuffer (indent + "class [" + (m_packageVMName.length () > 0 ? m_packageVMName + "/" : "") + m_name + "] descriptor:");
    153 
    154         for (int m = 0; m < m_methods.length; ++ m)
    155         {
    156             s.append (EOL);
    157             s.append (m_methods [m].toString (indent + INDENT_INCREMENT));
    158         }
    159 
    160         return s.toString ();
    161     }
    162 
    163     // protected: .............................................................
    164 
    165     // package: ...............................................................
    166 
    167 
    168     static ClassDescriptor readExternal (final DataInput in)
    169         throws IOException
    170     {
    171         final String packageVMName = in.readUTF ();
    172         final String name = in.readUTF ();
    173 
    174         final long stamp = in.readLong ();
    175 
    176         final byte srcFileNameFlag = in.readByte ();
    177         final String srcFileName = srcFileNameFlag != 0 ? in.readUTF () : null;
    178 
    179         final int length = in.readInt ();
    180         final MethodDescriptor [] methods = new MethodDescriptor [length];
    181         for (int i = 0; i < length; ++ i)
    182         {
    183             methods [i] = MethodDescriptor.readExternal (in);
    184         }
    185 
    186         return new ClassDescriptor (packageVMName, name, stamp, srcFileName, methods);
    187     }
    188 
    189     static void writeExternal (final ClassDescriptor cls, final DataOutput out)
    190         throws IOException
    191     {
    192         out.writeUTF (cls.m_packageVMName);
    193         out.writeUTF (cls.m_name);
    194 
    195         out.writeLong (cls.m_stamp);
    196 
    197         if (cls.m_srcFileName != null)
    198         {
    199             out.writeByte (1);
    200             out.writeUTF (cls.m_srcFileName);
    201         }
    202         else
    203         {
    204             out.writeByte (0);
    205         }
    206 
    207         final MethodDescriptor [] methods = cls.m_methods;
    208         final int length = methods.length;
    209         out.writeInt (length);
    210         for (int i = 0; i < length; ++ i)
    211         {
    212             MethodDescriptor.writeExternal (methods [i], out);
    213         }
    214 
    215         // [m_hash and m_hasCompleteLineNumberInfo are transient data]
    216     }
    217 
    218     // private: ...............................................................
    219 
    220 
    221     private final String m_packageVMName; // in JVM format, no trailing '/' [never null]
    222     private final String m_name; // relative to (m_packageName + '/') [never null]
    223     private final long m_stamp;
    224     private final String m_srcFileName; // relative to (m_packageName + '/') [can be null]
    225     private final MethodDescriptor [] m_methods; // [never null, could be empty]
    226 
    227     private final boolean m_hasCompleteLineNumberInfo;
    228     private transient int m_hash;
    229 
    230 } // end of class
    231 // ----------------------------------------------------------------------------
    232