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