477 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			477 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C#
		
	
	
| using System;
 | |
| using System.IO;
 | |
| using System.Collections.Generic;
 | |
| using System.Text;
 | |
| using OpenSim.Scripting.EmbeddedJVM.Types;
 | |
| 
 | |
| namespace OpenSim.Scripting.EmbeddedJVM
 | |
| {
 | |
|     public class ClassRecord
 | |
|     {
 | |
|         private ushort _majorVersion;
 | |
|         private ushort _minorVersion;
 | |
|         private ushort _constantPoolCount;
 | |
|         private ushort _accessFlags;
 | |
|         private ushort _thisClass;
 | |
|         private ushort _supperClass;
 | |
|         private ushort _interfaceCount;
 | |
|         private ushort _fieldCount;
 | |
|         private ushort _methodCount;
 | |
|         private ushort _attributeCount;
 | |
|         private string _name;
 | |
|         public Dictionary<string, BaseType> StaticFields = new Dictionary<string, BaseType>();
 | |
|         public PoolClass mClass;
 | |
| 
 | |
|         public List<PoolItem> _constantsPool = new List<PoolItem>();
 | |
|         private List<MethodInfo> _methodsList = new List<MethodInfo>();
 | |
|         private List<FieldInfo> _fieldList = new List<FieldInfo>();
 | |
| 
 | |
|         public ClassRecord()
 | |
|         {
 | |
| 
 | |
|         }
 | |
| 
 | |
|         public ClassInstance CreateNewInstance()
 | |
|         {
 | |
|             return new ClassInstance();
 | |
|         }
 | |
| 
 | |
|         public void LoadClassFromFile(string fileName)
 | |
|         {
 | |
|             Console.WriteLine("loading script " + fileName);
 | |
|             FileStream fs = File.OpenRead(fileName);
 | |
|             this.LoadClassFromBytes(ReadFully(fs));
 | |
|             fs.Close();
 | |
|         }
 | |
| 
 | |
|         public void LoadClassFromBytes(byte[] data)
 | |
|         {
 | |
|             int i = 0;
 | |
|             i += 4;
 | |
|             _minorVersion = (ushort)((data[i++] << 8) + data[i++]  );
 | |
|             _majorVersion = (ushort)((data[i++] << 8) + data[i++]  );
 | |
|             _constantPoolCount = (ushort)((data[i++] << 8) + data[i++]  );
 | |
|            // Console.WriteLine("there should be " + _constantPoolCount + " items in the pool");
 | |
|             for (int count = 0; count < _constantPoolCount -1 ; count++)
 | |
|             {
 | |
|                 //read in the constant pool
 | |
|                 byte pooltype = data[i++];
 | |
|                 //Console.WriteLine("#" +count +": new constant type = " +pooltype);
 | |
|                 //Console.WriteLine("start position is: " + i);
 | |
|                 switch (pooltype)
 | |
|                 {
 | |
|                     case 1:  //Utf8
 | |
|                         ushort uLength = (ushort)((data[i++] << 8) + data[i++]  );
 | |
| 
 | |
|                        // Console.WriteLine("new utf8 type, length is " + uLength);
 | |
|                         PoolUtf8 utf8 = new PoolUtf8();
 | |
|                         utf8.readValue(data, ref i, uLength);
 | |
|                         this._constantsPool.Add(utf8);
 | |
|                         break;
 | |
|                     case 3: //Int
 | |
|                         break;
 | |
|                     case 7: //Class
 | |
|                         PoolClass pClass = new PoolClass(this);
 | |
|                         pClass.readValue(data, ref i);
 | |
|                         this._constantsPool.Add(pClass);
 | |
|                         break;
 | |
|                     case 10: //Method
 | |
|                         PoolMethodRef pMeth = new PoolMethodRef(this);
 | |
|                         pMeth.readValue(data, ref i);
 | |
|                         this._constantsPool.Add(pMeth);
 | |
|                         break;
 | |
|                     case 12:  //NamedType
 | |
|                         PoolNamedType pNamed = new PoolNamedType(this);
 | |
|                         pNamed.readValue(data, ref i);
 | |
|                         this._constantsPool.Add(pNamed);
 | |
|                         break;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             _accessFlags = (ushort)((data[i++] << 8) + data[i++]  );
 | |
|             _thisClass = (ushort)((data[i++] << 8) + data[i++]  );
 | |
|             _supperClass = (ushort)((data[i++] << 8) + data[i++]  );
 | |
| 
 | |
|             if (this._constantsPool[this._thisClass - 1] is PoolClass)
 | |
|             {
 | |
|                 this.mClass = ((PoolClass)this._constantsPool[this._thisClass - 1]);
 | |
|             }
 | |
| 
 | |
|             _interfaceCount = (ushort)((data[i++] << 8) + data[i++]);
 | |
|             //should now read in the info for each interface
 | |
|             _fieldCount = (ushort)((data[i++] << 8) + data[i++]);
 | |
|             //should now read in the info for each field
 | |
|             _methodCount = (ushort)((data[i++] << 8) + data[i++]);
 | |
|             for (int count = 0; count < _methodCount; count++)
 | |
|             {
 | |
|                 MethodInfo methInf = new MethodInfo(this);
 | |
|                 methInf.ReadData(data, ref i);
 | |
|                 this._methodsList.Add(methInf);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void AddMethodsToMemory(MethodMemory memory)
 | |
|         {
 | |
|             for (int count = 0; count < _methodCount; count++)
 | |
|             {
 | |
|                 this._methodsList[count].AddMethodCode(memory);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public bool StartMethod(Thread thread, string methodName)
 | |
|         {
 | |
|             for (int count = 0; count < _methodCount; count++)
 | |
|             {
 | |
|                 if (this._constantsPool[this._methodsList[count].NameIndex-1] is PoolUtf8)
 | |
|                 {
 | |
|                     if (((PoolUtf8)this._constantsPool[this._methodsList[count].NameIndex-1]).Value == methodName)
 | |
|                     {
 | |
|                         //Console.WriteLine("found method: " + ((PoolUtf8)this._constantsPool[this._methodsList[count].NameIndex - 1]).Value);
 | |
|                         thread.SetPC(this._methodsList[count].CodePointer);
 | |
|                         return true;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         public void PrintToConsole()
 | |
|         {
 | |
|             Console.WriteLine("Class File:");
 | |
|            Console.WriteLine("Major version: " + _majorVersion);
 | |
|            Console.WriteLine("Minor version: " + _minorVersion);
 | |
|             Console.WriteLine("Pool size: " + _constantPoolCount);
 | |
| 
 | |
|             for (int i = 0; i < _constantsPool.Count; i++)
 | |
|             {
 | |
|                 this._constantsPool[i].Print();
 | |
|             }
 | |
| 
 | |
|            Console.WriteLine("Access flags: " + _accessFlags);
 | |
|            Console.WriteLine("This class: " + _thisClass );
 | |
|            Console.WriteLine("Super class: " + _supperClass);
 | |
| 
 | |
|             for (int count = 0; count < _methodCount; count++)
 | |
|             {
 | |
|                 Console.WriteLine();
 | |
|                 this._methodsList[count].Print();
 | |
|             }
 | |
| 
 | |
|            Console.WriteLine("class name is " + this.mClass.Name.Value);
 | |
|         }
 | |
| 
 | |
|         public static byte[] ReadFully(Stream stream)
 | |
|         {
 | |
|             byte[] buffer = new byte[1024];
 | |
|             using (MemoryStream ms = new MemoryStream())
 | |
|             {
 | |
|                 while (true)
 | |
|                 {
 | |
|                     int read = stream.Read(buffer, 0, buffer.Length);
 | |
|                     if (read <= 0)
 | |
|                         return ms.ToArray();
 | |
|                     ms.Write(buffer, 0, read);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #region nested classes
 | |
|         public class PoolItem
 | |
|         {
 | |
|             public virtual void Print()
 | |
|             {
 | |
| 
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public class PoolUtf8 : PoolItem
 | |
|         {
 | |
|             public string Value = "";
 | |
| 
 | |
|             public void readValue(byte[] data,ref int pointer , int length)
 | |
|             {
 | |
|                 for (int i = 0; i < length; i++)
 | |
|                 {
 | |
|                     int a =(int) data[pointer++];
 | |
|                     if ((a & 0x80) == 0)
 | |
|                     {
 | |
|                         Value = Value + (char)a;
 | |
|                     }
 | |
|                     else if ((a & 0x20) == 0)
 | |
|                     {
 | |
|                         int b = (int) data[pointer++];
 | |
|                         Value = Value + (char)(((a & 0x1f) << 6) + (b & 0x3f));      
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         int b = (int)data[pointer++];
 | |
|                         int c = (int)data[pointer++];
 | |
|                         Value = Value + (char)(((a & 0xf) << 12) + ((b & 0x3f) << 6) + (c & 0x3f));            
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             public override void Print()
 | |
|             {
 | |
|                Console.WriteLine("Utf8 type: " + Value);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private class PoolInt : PoolItem
 | |
|         {
 | |
| 
 | |
|         }
 | |
| 
 | |
|         public class PoolClass : PoolItem
 | |
|         {
 | |
|             //public string name = "";
 | |
|             public ushort namePointer = 0;
 | |
|             private ClassRecord parent;
 | |
|             public PoolUtf8 Name;
 | |
| 
 | |
|             public PoolClass(ClassRecord paren)
 | |
|             {
 | |
|                 parent = paren;
 | |
|             }
 | |
| 
 | |
|             public void readValue(byte[] data, ref int pointer)
 | |
|             {
 | |
|                 namePointer = (ushort)((data[pointer++] << 8) + data[pointer++] );
 | |
|             }
 | |
| 
 | |
|             public override void Print()
 | |
|             {
 | |
|                 this.Name = ((PoolUtf8)this.parent._constantsPool[namePointer - 1]);
 | |
|                 Console.Write("Class type: " + namePointer);
 | |
|                 Console.WriteLine(" // " + ((PoolUtf8)this.parent._constantsPool[namePointer - 1]).Value);
 | |
|                 
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public class PoolMethodRef : PoolItem
 | |
|         {
 | |
|             public ushort classPointer = 0;
 | |
|             public ushort nameTypePointer = 0;
 | |
|             public PoolNamedType mNameType;
 | |
|             public PoolClass mClass;
 | |
|             private ClassRecord parent;
 | |
| 
 | |
|             public PoolMethodRef(ClassRecord paren)
 | |
|             {
 | |
|                 parent = paren;
 | |
|             }
 | |
| 
 | |
|             public void readValue(byte[] data, ref int pointer)
 | |
|             {
 | |
|                 classPointer = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                 nameTypePointer = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|             }
 | |
| 
 | |
|             public override void Print()
 | |
|             {
 | |
|                 this.mNameType = ((PoolNamedType)this.parent._constantsPool[nameTypePointer - 1]);
 | |
|                 this.mClass = ((PoolClass)this.parent._constantsPool[classPointer - 1]);
 | |
|                Console.WriteLine("MethodRef type: " + classPointer + " , " + nameTypePointer); 
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public class PoolNamedType : PoolItem
 | |
|         {
 | |
|             public ushort namePointer = 0;
 | |
|             public ushort typePointer = 0;
 | |
|             private ClassRecord parent;
 | |
|             public PoolUtf8 Name;
 | |
|             public PoolUtf8 Type;
 | |
| 
 | |
|             public PoolNamedType(ClassRecord paren)
 | |
|             {
 | |
|                 parent = paren;
 | |
|             }
 | |
| 
 | |
|             public void readValue(byte[] data, ref int pointer)
 | |
|             {
 | |
|                 namePointer = (ushort)((data[pointer++] << 8) + data[pointer++] );
 | |
|                 typePointer = (ushort)((data[pointer++] << 8) + data[pointer++] );
 | |
|             }
 | |
| 
 | |
|             public override void Print()
 | |
|             {
 | |
|                 Name = ((PoolUtf8)this.parent._constantsPool[namePointer-1]);
 | |
|                 Type = ((PoolUtf8)this.parent._constantsPool[typePointer-1]);
 | |
|                 Console.Write("Named type: " + namePointer + " , " + typePointer );
 | |
|                 Console.WriteLine(" // "+ ((PoolUtf8)this.parent._constantsPool[namePointer-1]).Value);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         //***********************
 | |
|         public class MethodInfo
 | |
|         {
 | |
|             public ushort AccessFlags = 0;
 | |
|             public ushort NameIndex = 0;
 | |
|             public string Name = "";
 | |
|             public ushort DescriptorIndex = 0;
 | |
|             public ushort AttributeCount = 0;
 | |
|             public List<MethodAttribute> Attributes = new List<MethodAttribute>();
 | |
|             private ClassRecord parent;
 | |
|             public int CodePointer = 0;
 | |
|  
 | |
|             public MethodInfo(ClassRecord paren)
 | |
|             {
 | |
|                 parent = paren;
 | |
|             }
 | |
| 
 | |
|             public void AddMethodCode(MethodMemory memory)
 | |
|             {
 | |
|                 Array.Copy(this.Attributes[0].Code, 0, memory.MethodBuffer, memory.NextMethodPC, this.Attributes[0].Code.Length);
 | |
|                 memory.Methodcount++;
 | |
|                 this.CodePointer = memory.NextMethodPC;
 | |
|                 memory.NextMethodPC += this.Attributes[0].Code.Length;
 | |
|             }
 | |
| 
 | |
|             public void ReadData(byte[] data, ref int pointer)
 | |
|             {
 | |
|                 AccessFlags = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                 NameIndex = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                 DescriptorIndex = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                 AttributeCount = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                 for(int i =0; i< AttributeCount; i++)
 | |
|                 {
 | |
|                     MethodAttribute attri = new MethodAttribute(this.parent);
 | |
|                     attri.ReadData(data, ref pointer);
 | |
|                     this.Attributes.Add(attri);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             public void Print()
 | |
|             {
 | |
|                Console.WriteLine("Method Info Struct: ");
 | |
|               Console.WriteLine("AccessFlags: " + AccessFlags);
 | |
|               Console.WriteLine("NameIndex: " + NameIndex +" // "+ ((PoolUtf8)this.parent._constantsPool[NameIndex-1]).Value);
 | |
|               Console.WriteLine("DescriptorIndex: " + DescriptorIndex + " // "+ ((PoolUtf8)this.parent._constantsPool[DescriptorIndex-1]).Value);
 | |
|               Console.WriteLine("Attribute Count:" + AttributeCount);
 | |
|                 for (int i = 0; i < AttributeCount; i++)
 | |
|                 {
 | |
|                     this.Attributes[i].Print();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             public class MethodAttribute
 | |
|             {
 | |
|                 public ushort NameIndex = 0;
 | |
|                 public string Name = "";
 | |
|                 public Int32 Length = 0;
 | |
|                 //for now only support code attribute
 | |
|                 public ushort MaxStack = 0;
 | |
|                 public ushort MaxLocals = 0;
 | |
|                 public Int32 CodeLength = 0;
 | |
|                 public byte[] Code;
 | |
|                 public ushort ExceptionTableLength = 0;
 | |
|                 public ushort SubAttributeCount = 0;
 | |
|                 public List<SubAttribute> SubAttributes = new List<SubAttribute>();
 | |
|                 private ClassRecord parent;
 | |
| 
 | |
|                 public MethodAttribute(ClassRecord paren)
 | |
|                 {
 | |
|                     parent = paren;
 | |
|                 }
 | |
| 
 | |
|                 public void ReadData(byte[] data, ref int pointer)
 | |
|                 {
 | |
|                     NameIndex = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                     Length = (Int32)((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]);
 | |
|                     MaxStack = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                     MaxLocals = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                     CodeLength = (Int32)((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]);
 | |
|                     Code = new byte[CodeLength];
 | |
|                     for (int i = 0; i < CodeLength; i++)
 | |
|                     {
 | |
|                         Code[i] = data[pointer++];
 | |
|                     }
 | |
|                     ExceptionTableLength = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                     SubAttributeCount = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                     for (int i = 0; i < SubAttributeCount; i++)
 | |
|                     {
 | |
|                         SubAttribute subAttri = new SubAttribute(this.parent);
 | |
|                         subAttri.ReadData(data, ref pointer);
 | |
|                         this.SubAttributes.Add(subAttri);
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 public void Print()
 | |
|                 {
 | |
|                    Console.WriteLine("Method Attribute: ");
 | |
|                  Console.WriteLine("Name Index: " + NameIndex + " // "+ ((PoolUtf8)this.parent._constantsPool[NameIndex-1]).Value);
 | |
|                   Console.WriteLine("Length: " + Length);
 | |
|                   Console.WriteLine("MaxStack: " + MaxStack);
 | |
|                   Console.WriteLine("MaxLocals: " + MaxLocals);
 | |
|                  Console.WriteLine("CodeLength: " + CodeLength);
 | |
|                     for (int i = 0; i < Code.Length; i++)
 | |
|                     {
 | |
|                         Console.WriteLine("OpCode #" + i + " is: " + Code[i]);
 | |
|                     }
 | |
|                     Console.WriteLine("SubAttributes: " + SubAttributeCount);
 | |
|                     for (int i = 0; i < SubAttributeCount; i++)
 | |
|                     {
 | |
|                         this.SubAttributes[i].Print();
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 public class SubAttribute
 | |
|                 {
 | |
|                     public ushort NameIndex = 0;
 | |
|                     public string Name = "";
 | |
|                     public Int32 Length = 0;
 | |
|                     public byte[] Data;
 | |
|                     private ClassRecord parent;
 | |
| 
 | |
|                     public SubAttribute(ClassRecord paren)
 | |
|                     {
 | |
|                         parent = paren;
 | |
|                     }
 | |
| 
 | |
|                     public void ReadData(byte[] data, ref int pointer)
 | |
|                     {
 | |
|                         NameIndex = (ushort)((data[pointer++] << 8) + data[pointer++]);
 | |
|                         Length = (Int32)((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]);
 | |
|                         Data = new byte[Length];
 | |
|                         for (int i = 0; i < Length; i++)
 | |
|                         {
 | |
|                             Data[i] = data[pointer++];
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     public void Print()
 | |
|                     {
 | |
|                         Console.WriteLine("SubAttribute: NameIndex: " + NameIndex + " // " + ((PoolUtf8)this.parent._constantsPool[NameIndex - 1]).Value);
 | |
|                     }
 | |
| 
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|         }
 | |
|         private class InterfaceInfo
 | |
|         {
 | |
|             public void ReadData(byte[] data, ref int i)
 | |
|             {
 | |
| 
 | |
|             }
 | |
|         }
 | |
|         private class FieldInfo
 | |
|         {
 | |
|             public void ReadData(byte[] data, ref int i)
 | |
|             {
 | |
| 
 | |
|             }
 | |
|         }
 | |
|         private class AttributeInfo
 | |
|         {
 | |
|             public void ReadData(byte[] data, ref int i)
 | |
|             {
 | |
| 
 | |
|             }
 | |
|         }
 | |
|         #endregion
 | |
| 
 | |
|     }
 | |
| }
 |