• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ClassDescriptor(final String packageVMName, final String name, final long stamp, final String srcFileName, final MethodDescriptor [] methods)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 
equals(final Object rhs)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 
hashCode()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 
getPackageVMName()100     public final String getPackageVMName ()
101     {
102         return m_packageVMName;
103     }
104 
getName()105     public final String getName ()
106     {
107         return m_name;
108     }
109 
getStamp()110     public final long getStamp ()
111     {
112         return m_stamp;
113     }
114 
getClassVMName()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 
getSrcFileName()124     public final String getSrcFileName ()
125     {
126         return m_srcFileName;
127     }
128 
getMethods()129     public final MethodDescriptor [] getMethods ()
130     {
131         return m_methods; // no defensive copy
132     }
133 
hasSrcFileInfo()134     public final boolean hasSrcFileInfo ()
135     {
136         return m_srcFileName != null;
137     }
138 
hasCompleteLineNumberInfo()139     public final boolean hasCompleteLineNumberInfo ()
140     {
141         return m_hasCompleteLineNumberInfo;
142     }
143 
144 
toString()145     public String toString ()
146     {
147         return toString ("");
148     }
149 
toString(final String indent)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 
readExternal(final DataInput in)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 
writeExternal(final ClassDescriptor cls, final DataOutput out)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