ClassRecord.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using OpenSim.Scripting.EmbeddedJVM.Types;
  6. namespace OpenSim.Scripting.EmbeddedJVM
  7. {
  8. public class ClassRecord
  9. {
  10. private ushort _majorVersion;
  11. private ushort _minorVersion;
  12. private ushort _constantPoolCount;
  13. private ushort _accessFlags;
  14. private ushort _thisClass;
  15. private ushort _supperClass;
  16. private ushort _interfaceCount;
  17. private ushort _fieldCount;
  18. private ushort _methodCount;
  19. private ushort _attributeCount;
  20. private string _name;
  21. public Dictionary<string, BaseType> StaticFields = new Dictionary<string, BaseType>();
  22. public PoolClass mClass;
  23. public List<PoolItem> _constantsPool = new List<PoolItem>();
  24. private List<MethodInfo> _methodsList = new List<MethodInfo>();
  25. private List<FieldInfo> _fieldList = new List<FieldInfo>();
  26. public ClassRecord()
  27. {
  28. }
  29. public ClassInstance CreateNewInstance()
  30. {
  31. return new ClassInstance();
  32. }
  33. public void LoadClassFromFile(string fileName)
  34. {
  35. FileStream fs = File.OpenRead(fileName);
  36. this.LoadClassFromBytes(ReadFully(fs));
  37. fs.Close();
  38. }
  39. public void LoadClassFromBytes(byte[] data)
  40. {
  41. int i = 0;
  42. i += 4;
  43. _minorVersion = (ushort)((data[i++] << 8) + data[i++] );
  44. _majorVersion = (ushort)((data[i++] << 8) + data[i++] );
  45. _constantPoolCount = (ushort)((data[i++] << 8) + data[i++] );
  46. //Console.WriteLine("there should be " + _constantPoolCount + " items in the pool");
  47. for (int count = 0; count < _constantPoolCount -1 ; count++)
  48. {
  49. //read in the constant pool
  50. byte pooltype = data[i++];
  51. //Console.WriteLine("#" +count +": new constant type = " +pooltype);
  52. //Console.WriteLine("start position is: " + i);
  53. switch (pooltype)
  54. {
  55. case 1: //Utf8
  56. ushort uLength = (ushort)((data[i++] << 8) + data[i++] );
  57. // Console.WriteLine("new utf8 type, length is " + uLength);
  58. PoolUtf8 utf8 = new PoolUtf8();
  59. utf8.readValue(data, ref i, uLength);
  60. this._constantsPool.Add(utf8);
  61. break;
  62. case 3: //Int
  63. break;
  64. case 7: //Class
  65. PoolClass pClass = new PoolClass(this);
  66. pClass.readValue(data, ref i);
  67. this._constantsPool.Add(pClass);
  68. break;
  69. case 10: //Method
  70. PoolMethodRef pMeth = new PoolMethodRef(this);
  71. pMeth.readValue(data, ref i);
  72. this._constantsPool.Add(pMeth);
  73. break;
  74. case 12: //NamedType
  75. PoolNamedType pNamed = new PoolNamedType(this);
  76. pNamed.readValue(data, ref i);
  77. this._constantsPool.Add(pNamed);
  78. break;
  79. }
  80. }
  81. _accessFlags = (ushort)((data[i++] << 8) + data[i++] );
  82. _thisClass = (ushort)((data[i++] << 8) + data[i++] );
  83. _supperClass = (ushort)((data[i++] << 8) + data[i++] );
  84. if (this._constantsPool[this._thisClass - 1] is PoolClass)
  85. {
  86. this.mClass = ((PoolClass)this._constantsPool[this._thisClass - 1]);
  87. }
  88. _interfaceCount = (ushort)((data[i++] << 8) + data[i++]);
  89. //should now read in the info for each interface
  90. _fieldCount = (ushort)((data[i++] << 8) + data[i++]);
  91. //should now read in the info for each field
  92. _methodCount = (ushort)((data[i++] << 8) + data[i++]);
  93. for (int count = 0; count < _methodCount; count++)
  94. {
  95. MethodInfo methInf = new MethodInfo(this);
  96. methInf.ReadData(data, ref i);
  97. this._methodsList.Add(methInf);
  98. }
  99. }
  100. public void AddMethodsToMemory(MethodMemory memory)
  101. {
  102. for (int count = 0; count < _methodCount; count++)
  103. {
  104. this._methodsList[count].AddMethodCode(memory);
  105. }
  106. }
  107. public bool StartMethod(Thread thread, string methodName)
  108. {
  109. for (int count = 0; count < _methodCount; count++)
  110. {
  111. if (this._constantsPool[this._methodsList[count].NameIndex-1] is PoolUtf8)
  112. {
  113. if (((PoolUtf8)this._constantsPool[this._methodsList[count].NameIndex-1]).Value == methodName)
  114. {
  115. //Console.WriteLine("found method: " + ((PoolUtf8)this._constantsPool[this._methodsList[count].NameIndex - 1]).Value);
  116. thread.SetPC(this._methodsList[count].CodePointer);
  117. return true;
  118. }
  119. }
  120. }
  121. return false;
  122. }
  123. public void PrintToConsole()
  124. {
  125. // Console.WriteLine("Class File:");
  126. // Console.WriteLine("Major version: " + _majorVersion);
  127. // Console.WriteLine("Minor version: " + _minorVersion);
  128. //Console.WriteLine("Pool size: " + _constantPoolCount);
  129. for (int i = 0; i < _constantsPool.Count; i++)
  130. {
  131. this._constantsPool[i].Print();
  132. }
  133. // Console.WriteLine("Access flags: " + _accessFlags);
  134. // Console.WriteLine("This class: " + _thisClass );
  135. // Console.WriteLine("Super class: " + _supperClass);
  136. for (int count = 0; count < _methodCount; count++)
  137. {
  138. Console.WriteLine();
  139. this._methodsList[count].Print();
  140. }
  141. // Console.WriteLine("class name is " + this.mClass.Name.Value);
  142. }
  143. public static byte[] ReadFully(Stream stream)
  144. {
  145. byte[] buffer = new byte[1024];
  146. using (MemoryStream ms = new MemoryStream())
  147. {
  148. while (true)
  149. {
  150. int read = stream.Read(buffer, 0, buffer.Length);
  151. if (read <= 0)
  152. return ms.ToArray();
  153. ms.Write(buffer, 0, read);
  154. }
  155. }
  156. }
  157. #region nested classes
  158. public class PoolItem
  159. {
  160. public virtual void Print()
  161. {
  162. }
  163. }
  164. public class PoolUtf8 : PoolItem
  165. {
  166. public string Value = "";
  167. public void readValue(byte[] data,ref int pointer , int length)
  168. {
  169. for (int i = 0; i < length; i++)
  170. {
  171. int a =(int) data[pointer++];
  172. if ((a & 0x80) == 0)
  173. {
  174. Value = Value + (char)a;
  175. }
  176. else if ((a & 0x20) == 0)
  177. {
  178. int b = (int) data[pointer++];
  179. Value = Value + (char)(((a & 0x1f) << 6) + (b & 0x3f));
  180. }
  181. else
  182. {
  183. int b = (int)data[pointer++];
  184. int c = (int)data[pointer++];
  185. Value = Value + (char)(((a & 0xf) << 12) + ((b & 0x3f) << 6) + (c & 0x3f));
  186. }
  187. }
  188. }
  189. public override void Print()
  190. {
  191. // Console.WriteLine("Utf8 type: " + Value);
  192. }
  193. }
  194. private class PoolInt : PoolItem
  195. {
  196. }
  197. public class PoolClass : PoolItem
  198. {
  199. //public string name = "";
  200. public ushort namePointer = 0;
  201. private ClassRecord parent;
  202. public PoolUtf8 Name;
  203. public PoolClass(ClassRecord paren)
  204. {
  205. parent = paren;
  206. }
  207. public void readValue(byte[] data, ref int pointer)
  208. {
  209. namePointer = (ushort)((data[pointer++] << 8) + data[pointer++] );
  210. }
  211. public override void Print()
  212. {
  213. this.Name = ((PoolUtf8)this.parent._constantsPool[namePointer - 1]);
  214. //Console.Write("Class type: " + namePointer);
  215. //Console.WriteLine(" // " + ((PoolUtf8)this.parent._constantsPool[namePointer - 1]).Value);
  216. }
  217. }
  218. public class PoolMethodRef : PoolItem
  219. {
  220. public ushort classPointer = 0;
  221. public ushort nameTypePointer = 0;
  222. public PoolNamedType mNameType;
  223. public PoolClass mClass;
  224. private ClassRecord parent;
  225. public PoolMethodRef(ClassRecord paren)
  226. {
  227. parent = paren;
  228. }
  229. public void readValue(byte[] data, ref int pointer)
  230. {
  231. classPointer = (ushort)((data[pointer++] << 8) + data[pointer++]);
  232. nameTypePointer = (ushort)((data[pointer++] << 8) + data[pointer++]);
  233. }
  234. public override void Print()
  235. {
  236. this.mNameType = ((PoolNamedType)this.parent._constantsPool[nameTypePointer - 1]);
  237. this.mClass = ((PoolClass)this.parent._constantsPool[classPointer - 1]);
  238. // Console.WriteLine("MethodRef type: " + classPointer + " , " + nameTypePointer);
  239. }
  240. }
  241. public class PoolNamedType : PoolItem
  242. {
  243. public ushort namePointer = 0;
  244. public ushort typePointer = 0;
  245. private ClassRecord parent;
  246. public PoolUtf8 Name;
  247. public PoolUtf8 Type;
  248. public PoolNamedType(ClassRecord paren)
  249. {
  250. parent = paren;
  251. }
  252. public void readValue(byte[] data, ref int pointer)
  253. {
  254. namePointer = (ushort)((data[pointer++] << 8) + data[pointer++] );
  255. typePointer = (ushort)((data[pointer++] << 8) + data[pointer++] );
  256. }
  257. public override void Print()
  258. {
  259. Name = ((PoolUtf8)this.parent._constantsPool[namePointer-1]);
  260. Type = ((PoolUtf8)this.parent._constantsPool[typePointer-1]);
  261. //Console.Write("Named type: " + namePointer + " , " + typePointer );
  262. //Console.WriteLine(" // "+ ((PoolUtf8)this.parent._constantsPool[namePointer-1]).Value);
  263. }
  264. }
  265. //***********************
  266. public class MethodInfo
  267. {
  268. public ushort AccessFlags = 0;
  269. public ushort NameIndex = 0;
  270. public string Name = "";
  271. public ushort DescriptorIndex = 0;
  272. public ushort AttributeCount = 0;
  273. public List<MethodAttribute> Attributes = new List<MethodAttribute>();
  274. private ClassRecord parent;
  275. public int CodePointer = 0;
  276. public MethodInfo(ClassRecord paren)
  277. {
  278. parent = paren;
  279. }
  280. public void AddMethodCode(MethodMemory memory)
  281. {
  282. Array.Copy(this.Attributes[0].Code, 0, memory.MethodBuffer, memory.NextMethodPC, this.Attributes[0].Code.Length);
  283. memory.Methodcount++;
  284. this.CodePointer = memory.NextMethodPC;
  285. memory.NextMethodPC += this.Attributes[0].Code.Length;
  286. }
  287. public void ReadData(byte[] data, ref int pointer)
  288. {
  289. AccessFlags = (ushort)((data[pointer++] << 8) + data[pointer++]);
  290. NameIndex = (ushort)((data[pointer++] << 8) + data[pointer++]);
  291. DescriptorIndex = (ushort)((data[pointer++] << 8) + data[pointer++]);
  292. AttributeCount = (ushort)((data[pointer++] << 8) + data[pointer++]);
  293. for(int i =0; i< AttributeCount; i++)
  294. {
  295. MethodAttribute attri = new MethodAttribute(this.parent);
  296. attri.ReadData(data, ref pointer);
  297. this.Attributes.Add(attri);
  298. }
  299. }
  300. public void Print()
  301. {
  302. // Console.WriteLine("Method Info Struct: ");
  303. // Console.WriteLine("AccessFlags: " + AccessFlags);
  304. // Console.WriteLine("NameIndex: " + NameIndex +" // "+ ((PoolUtf8)this.parent._constantsPool[NameIndex-1]).Value);
  305. // Console.WriteLine("DescriptorIndex: " + DescriptorIndex + " // "+ ((PoolUtf8)this.parent._constantsPool[DescriptorIndex-1]).Value);
  306. // Console.WriteLine("Attribute Count:" + AttributeCount);
  307. for (int i = 0; i < AttributeCount; i++)
  308. {
  309. this.Attributes[i].Print();
  310. }
  311. }
  312. public class MethodAttribute
  313. {
  314. public ushort NameIndex = 0;
  315. public string Name = "";
  316. public Int32 Length = 0;
  317. //for now only support code attribute
  318. public ushort MaxStack = 0;
  319. public ushort MaxLocals = 0;
  320. public Int32 CodeLength = 0;
  321. public byte[] Code;
  322. public ushort ExceptionTableLength = 0;
  323. public ushort SubAttributeCount = 0;
  324. public List<SubAttribute> SubAttributes = new List<SubAttribute>();
  325. private ClassRecord parent;
  326. public MethodAttribute(ClassRecord paren)
  327. {
  328. parent = paren;
  329. }
  330. public void ReadData(byte[] data, ref int pointer)
  331. {
  332. NameIndex = (ushort)((data[pointer++] << 8) + data[pointer++]);
  333. Length = (Int32)((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]);
  334. MaxStack = (ushort)((data[pointer++] << 8) + data[pointer++]);
  335. MaxLocals = (ushort)((data[pointer++] << 8) + data[pointer++]);
  336. CodeLength = (Int32)((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]);
  337. Code = new byte[CodeLength];
  338. for (int i = 0; i < CodeLength; i++)
  339. {
  340. Code[i] = data[pointer++];
  341. }
  342. ExceptionTableLength = (ushort)((data[pointer++] << 8) + data[pointer++]);
  343. SubAttributeCount = (ushort)((data[pointer++] << 8) + data[pointer++]);
  344. for (int i = 0; i < SubAttributeCount; i++)
  345. {
  346. SubAttribute subAttri = new SubAttribute(this.parent);
  347. subAttri.ReadData(data, ref pointer);
  348. this.SubAttributes.Add(subAttri);
  349. }
  350. }
  351. public void Print()
  352. {
  353. // Console.WriteLine("Method Attribute: ");
  354. // Console.WriteLine("Name Index: " + NameIndex + " // "+ ((PoolUtf8)this.parent._constantsPool[NameIndex-1]).Value);
  355. // Console.WriteLine("Length: " + Length);
  356. // Console.WriteLine("MaxStack: " + MaxStack);
  357. // Console.WriteLine("MaxLocals: " + MaxLocals);
  358. // Console.WriteLine("CodeLength: " + CodeLength);
  359. for (int i = 0; i < Code.Length; i++)
  360. {
  361. // Console.WriteLine("OpCode #" + i + " is: " + Code[i]);
  362. }
  363. // Console.WriteLine("SubAttributes: " + SubAttributeCount);
  364. for (int i = 0; i < SubAttributeCount; i++)
  365. {
  366. this.SubAttributes[i].Print();
  367. }
  368. }
  369. public class SubAttribute
  370. {
  371. public ushort NameIndex = 0;
  372. public string Name = "";
  373. public Int32 Length = 0;
  374. public byte[] Data;
  375. private ClassRecord parent;
  376. public SubAttribute(ClassRecord paren)
  377. {
  378. parent = paren;
  379. }
  380. public void ReadData(byte[] data, ref int pointer)
  381. {
  382. NameIndex = (ushort)((data[pointer++] << 8) + data[pointer++]);
  383. Length = (Int32)((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]);
  384. Data = new byte[Length];
  385. for (int i = 0; i < Length; i++)
  386. {
  387. Data[i] = data[pointer++];
  388. }
  389. }
  390. public void Print()
  391. {
  392. //Console.WriteLine("SubAttribute: NameIndex: " + NameIndex + " // " + ((PoolUtf8)this.parent._constantsPool[NameIndex - 1]).Value);
  393. }
  394. }
  395. }
  396. }
  397. private class InterfaceInfo
  398. {
  399. public void ReadData(byte[] data, ref int i)
  400. {
  401. }
  402. }
  403. private class FieldInfo
  404. {
  405. public void ReadData(byte[] data, ref int i)
  406. {
  407. }
  408. }
  409. private class AttributeInfo
  410. {
  411. public void ReadData(byte[] data, ref int i)
  412. {
  413. }
  414. }
  415. #endregion
  416. }
  417. }