ClassRecord.cs 18 KB

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