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