home | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (PEModule.java)

This example Scala source code file (PEModule.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Scala tags/keywords

assembly, assembly, constructorinfo, genericparamandconstraints, io, memberinfo, nio, pemodule, petype, runtimeexception, runtimeexception, sig, string, string, type, type

The Scala PEModule.java source code

/*
 * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
 */


package ch.epfl.lamp.compiler.msil;

import ch.epfl.lamp.compiler.msil.PEFile;
import ch.epfl.lamp.compiler.msil.PEFile.Sig;
import ch.epfl.lamp.compiler.msil.util.Signature;
import ch.epfl.lamp.compiler.msil.util.Table;
import ch.epfl.lamp.compiler.msil.util.Table.*;

import java.nio.ByteBuffer;

/** Represents a module corresponding to a PE/COFF file
 *
 * @author Nikolay Mihaylov
 * @version 1.0
 */
final class PEModule extends Module {

    //##########################################################################

    protected final PEFile pefile;

    private final int definingRow;

    private Type[] typeRefs = null;

    protected PEModule(PEFile pefile, int definingRow, String scopeName,
		       Assembly assem)
    {
	super(pefile.getName(), pefile.getAbsolutePath(), scopeName, assem);
	this.pefile = pefile;
        this.definingRow = definingRow;
	pefile.initModule(this);
	pefile.TypeDef.load(); // load into memory
	//loadTypes();
	//pefile.FieldDef.load();
	//pefile.MethodDef.load();
	loadGlobals();
    }

    //##########################################################################

    public Type GetType(String typeName) {
        initTypes();
	Object o = typesMap.get(typeName);
	if (o == null) {
	    //System.out.println("PEModule.GetType(): Unable to find type "
	    //                   + typeName + " int module " + this);
	    return null;
	}
	return o instanceof Type ? (Type)o
	    : getTypeDef(((Integer)o).intValue());
    }


    /** Load information about the types defined in this module.
     */
    protected void loadTypes() {
	typeRefs = new Type[pefile.TypeRef.rows];
	final int nbTypes = pefile.TypeDef.rows;
	for (int row = 2; row <= nbTypes; row++) {
	    String name = pefile.TypeDef(row).getFullName();
	    typesMap.put(name, new Integer(row));
	}
	this.types = new Type[nbTypes - 1];
	for (int row = 2; row <= nbTypes; row++) {
	    getTypeDef(row);
	}
    }

    /** Return the type defined at the given row in the TypeDef table.
     */
    Type getTypeDef(int row) {
	if (this.types[row - 2] != null)
	    return this.types[row - 2];

	TypeDef type = pefile.TypeDef(row);
	int attrs = type.Flags;
	String name = type.getFullName();

	Type declType = null;
	if (TypeAttributes.isNested(attrs)) {
	    for (int i = 1; i <= pefile.NestedClass.rows; i++) {
		pefile.NestedClass.readRow(i);
		if (pefile.NestedClass.NestedClass == row)
		    declType = getTypeDef
			(pefile.NestedClass.EnclosingClass);
	    }
	}
	Type t = new PEType
            (this, attrs, name, declType, Type.AuxAttr.None, pefile, row);
	types[row - 2] = t;
	addType(t);
        int[] tvarIdxes = pefile.GenericParam.getTVarIdxes(row);
        // if(tvarIdxes.length > 0) { System.out.println("Type: " + t); }
        for(int i = 0; i < tvarIdxes.length; i++) {
            GenericParamAndConstraints tvarAndConstraints = getTypeConstraints(tvarIdxes[i]);
            // add tvarAndConstraints as i-th TVar in t
            t.addTVar(tvarAndConstraints);
        }
	return t;
    }

    public GenericParamAndConstraints getTypeConstraints(int genParamIdx) {
        int tvarNumber = pefile.GenericParam(genParamIdx).Number;
        // tvarName can be null
        String tvarName = pefile.GenericParam.getName();
        boolean isInvariant = pefile.GenericParam.isInvariant();
        boolean isCovariant = pefile.GenericParam.isCovariant();
        boolean isContravariant = pefile.GenericParam.isContravariant();
        boolean isReferenceType = pefile.GenericParam.isReferenceType();
        boolean isValueType = pefile.GenericParam.isValueType();
        boolean hasDefaultConstructor = pefile.GenericParam.hasDefaultConstructor();
        // grab constraints
        int[] TypeDefOrRefIdxes = pefile.GenericParamConstraint.getTypeDefOrRefIdxes(genParamIdx);
        Type[] tCtrs = new Type[TypeDefOrRefIdxes.length];
        for(int i = 0; i < TypeDefOrRefIdxes.length; i++) {
            Type tConstraint = getTypeDefOrRef(TypeDefOrRefIdxes[i]);
            tCtrs[i] = tConstraint;
            // System.out.println("\t\tConstraint: " + tConstraint);
        }
        GenericParamAndConstraints res = new GenericParamAndConstraints(tvarNumber, tvarName, tCtrs,
                isInvariant, isCovariant, isContravariant,
                isReferenceType, isValueType, hasDefaultConstructor);
        return res;
    }

    /**
     * Load the desription of the module-global fields and methods
     */
    protected void loadGlobals() {
	//TODO:
    }

    protected void loadCustomAttributes(Type attributeType) {
        initAttributes(this, 1, Table.ModuleDef.ID, attributeType);
    }

    /** Return the type referenced by the given row in the TypeRef table.
     */
    Type getTypeRef(int row) {
        return getTypeRef(row, null);
    }

    /** Return the type referenced by the given row in the TypeRef table
     *  only if it resides in the given assembly.
     *  <i>Used by initCustomAttributes to avoid unnecessary loading
     *  of referenced assemblies.</i>
     */
    Type getTypeRef(int row, Assembly inAssembly) {
	Type type = typeRefs[row - 1];
	if (type != null)
	    return type;

	Table.TypeRef tr = pefile.TypeRef;
	tr.readRow(row);
	int tableId = Table.getTableId(Table._ResolutionScope,
				       tr.ResolutionScope);
	int refRow = tr.ResolutionScope >> Table.NoBits[Table._ResolutionScope];
	final String typeName = tr.getFullName();
	pefile.getTable(tableId).readRow(refRow);
	switch (tableId) {
	case AssemblyRef.ID:
	    String name = pefile.AssemblyRef.getName();
            if (inAssembly != null && !inAssembly.GetName().Name.equals(name))
                return null;
            Assembly assem = getAssembly(name);
	    type = assem.GetType(typeName);
	    if (type == null) {
                // HACK: the IKVM.OpenJDK.Core assembly is compiled against mscorlib.dll v2.0
                // The MSIL library cannot parse the v2.0 mscorlib because of generics, so we
                // use the v1.0
                // However, the java.io.FileDescriptor.FlushFileBuffers method uses a type
                // Microsoft.Win32.SafeHandles.SafeFileHandle, which only exists in mscorlib
                // v2.0
                // For now, jsut return Object (fine as long as we don't use that method).
                Assembly asmb = getAssembly("mscorlib");
                type = asmb.GetType("System.Object");
		//throw new RuntimeException("Failed to locate type " +
                                           //typeName + " in assembly " + assem);
	    }
	    break;
	case ModuleDef.ID:
	    assert refRow == 1;
	    type = this.GetType(typeName);
	    //assert type != null;
	    break;
	case TypeRef.ID:
        Type nestingType = getTypeRef(refRow);
        String nestedName = typeName;
	    type = nestingType.GetNestedType(nestedName);
	    break;
	case ModuleRef.ID:
            type = getAssembly(pefile.ModuleRef.getName()).GetType(typeName);
	default:
	    throw new RuntimeException(refRow + "@" + pefile.getTable(tableId).getTableName()/* PEFile.byte2hex(tableId)*/);
	}
	if (typeRefs[row - 1] != null)
	    System.out.println("TypeRef[" + PEFile.short2hex(row) + "] " +
			       "changing type " + typeRefs[row - 1] +
			       " for type " + type);
	typeRefs[row - 1] = type;
	assert type != null : "Couldn't find type " + typeName;
	return type;
    }

    private Assembly getAssembly(String name) {
        Assembly assem = Assembly.getAssembly(name);
        if (assem != null)
            return assem;
        java.io.File dir = pefile.getParentFile();
        assem = Assembly.LoadFrom(dir, name);
        if (assem != null)
            return assem;
        try {
            dir = pefile.getUnderlyingFile().getCanonicalFile().getParentFile();
        } catch (java.io.IOException e) {
            throw new RuntimeException(e);
        }
        assem = Assembly.LoadFrom(dir, name);
        if (assem != null)
            return assem;
        throw new RuntimeException("Cannot find assembly: " + name);

    }

    /** Return the type corresponding to TypeDefOrRef coded index.
     *  @param index - TypeDefOrRef coded index according to 23.2.6.
     */
    public Type getTypeDefOrRef(int index) {
	int tableId = Table.getTableId(Table._TypeDefOrRef, index);
	int row = index >> Table.NoBits[Table._TypeDefOrRef];
	Type type = null;
	switch (tableId) {
	case Table.TypeDef.ID:
	    type = getTypeDef(row);
	    break;
	case Table.TypeRef.ID:
	    return getTypeRef(row);
	case Table.TypeSpec.ID:
                Table.TypeSpec ts = pefile.TypeSpec;
                ts.readRow(row);
                int posInBlobStream = ts.Signature;
                byte[] blobArrWithLengthStripped = pefile.Blob.getBlob(posInBlobStream);
                byte[] compressedUInt = compressUInt(blobArrWithLengthStripped.length);
                byte[] byteArr = new byte[blobArrWithLengthStripped.length + compressedUInt.length];
                System.arraycopy(compressedUInt, 0, byteArr, 0, compressedUInt.length);
                System.arraycopy(blobArrWithLengthStripped, 0, byteArr, compressedUInt.length, blobArrWithLengthStripped.length);
                ByteBuffer buf = ByteBuffer.wrap(byteArr);
                Sig sig = pefile.new Sig(buf);
                int desc = sig.readByte();

                switch (desc) {

                    // GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncodred GenArgCount Type*
                    case Signature.ELEMENT_TYPE_GENERICINST:      // i.e. 0x15
                        int b = sig.readByte(); // i.e. (0x12 | 0x11)
                        /* TODO don't ignore b as done above */
                        Type instantiatedType = getTypeDefOrRef(sig.decodeInt());  // TypeDefOrRefEncoded
                        int numberOfTypeArgs = sig.decodeInt();    // GenArgCount
                        Type[] typeArgs = new Type[numberOfTypeArgs];
                        for (int iarg = 0; iarg < numberOfTypeArgs; iarg++) {
                            typeArgs[iarg] = sig.decodeType();       // Type*
                        }
                        type = new ConstructedType(instantiatedType, typeArgs);
                        break;

                    /* Miguel says: Actually the following grammar rule production is not among those for a TypeSpecBlob
                       but I've found it in assemblies compiled from C# 3.0.
                       See also duplicate code in PEFile.java */
                    case Signature.ELEMENT_TYPE_VAR:
                        int typeArgAsZeroBased = sig.decodeInt();
                        type = new Type.TMVarUsage(typeArgAsZeroBased, true);
                        break;

                    /* Miguel says: Actually the following grammar rule production is not among those for a TypeSpecBlob
                       but I've found it in assemblies compiled from C# 3.0.
                       See also duplicate code in PEFile.java */
                    case Signature.ELEMENT_TYPE_MVAR:
                        typeArgAsZeroBased = sig.decodeInt();
                        type = new Type.TMVarUsage(typeArgAsZeroBased, false);
                        break;

                    case Signature.ELEMENT_TYPE_SZARRAY:    // Single-dim array with 0 lower bound.
                        sig.skipCustomMods();
                        type = Type.mkArray(sig.decodeType(), 1);
                        break;

                    case Signature.ELEMENT_TYPE_ARRAY:
                        // <type>    ...   ...
                        // ArrayShape defined in 23.2.13 ArrayShape
                        Type elem = sig.decodeType();
                        int rank = sig.decodeInt();
                        int numSizes = sig.decodeInt();
                        for (int i = 0; i < numSizes; i++)
                            sig.decodeInt(); // TODO don't ignore
                        int numLoBounds = sig.decodeInt();
                        for (int i = 0; i < numLoBounds; i++)
                            sig.decodeInt(); // TODO don't ignore
                        type = Type.mkArray(elem, rank);
                        break;

                    default:
                        // TODO remaining grammar productions in 23.2.14 are for PTR and FNPTR only
	    throw new RuntimeException("PEModule.getTypeDefOrRef(): TypeSpec");
                }
                break;
	default:
	    throw new RuntimeException("PEModule.getTypeDefOrRef(): oops!");
	}
	return type;
    }

    private byte[] compressUInt(int u) {
        // 23.2 in Partition II
        // TODO add tests based on the examples in 23.2 in Partition II
        // the CCI implementation is WriteCompressedUInt

        /* informal discussion at http://www.cnblogs.com/AndersLiu/archive/2010/02/09/en-compressed-integer-in-metadata.html  */
        if (u <= 127 && 0 <= u) {
            return new byte[]{(byte) u};
        } else if (u > 127 && u <= (2 ^ 14 - 1)) {
            byte loByte = (byte)(u & 0xff);
            byte hiByte = (byte)((u >> 8) | 0x80);
            byte[] res = new byte[] { hiByte, loByte };
            return res;
        } else {
            byte b0 = (byte)(u & 0xff);
            byte b1 = (byte)((u & 0xff00)>>8);
            byte b2 = (byte)((u & 0xff0000)>>16);
            byte b3 = (byte)((u >> 24)|0xc0);
            byte[] res = new byte[] { b3, b2, b1, b0 };
            return res;
        }
    }

    /**
     * Returns the method defined at the given row of the MethodDef table
     *  by looking up the type that defines the method.
     */
    MethodBase getMethod(int row) {
	for (int i = 0; i < types.length; i++) {
	    PEType type = (PEType)types[i]; 
	    if ((type.methodListBeg <= row) && (row < type.methodListEnd)) {
		type.initMethods();
		return type.methoddefs[row - type.methodListBeg];
	    }
	}
	throw new RuntimeException("In module " + this
				   + ": cannot find type defining method 0x"
				   + PEFile.int2hex(row));
    }

    /** Returns the member referenced by the given row of the MemberRef table.
     */
    protected MemberInfo getMemberRef(int row) {
        return getMemberRef(row, null);
    }

    /** Returns the member referenced by the given row of the MemberRef table
     *  if defined in the given assembly.
     *  <i>Used by initCustomAttributes to avoid unnecessary loading of
     *  referenced assemblies</i>
     */
    protected MemberInfo getMemberRef(int row, Assembly inAssembly) {
	MemberInfo member = null;
	MemberRef mref = pefile.MemberRef;
	mref.readRow(row);
	int mtbl = Table.getTableId(Table._MemberRefParent, mref.Class);
	int mind = Table.getTableIndex(Table._MemberRefParent, mref.Class);
	switch (mtbl) {
	case TypeRef.ID:
	    Type type = getTypeRef(mind, inAssembly);
            if (type == null)
                return null;
            Sig sig = mref.getSignature();
            int callconv = sig.readByte(); // should be 0x20
            int paramCount = sig.decodeInt();
	    //sig.skipByte(Signature.ELEMENT_TYPE_BYREF); //from MethodDef
	    Type retType = sig.decodeRetType();
	    Type[] paramType = new Type[paramCount];
	    for (int i = 0; i < paramCount; i++)
		paramType[i] = sig.decodeParamType();

            String memberName = mref.getName();
            if (memberName.equals(ConstructorInfo.CTOR) ||
                memberName.equals(ConstructorInfo.CCTOR))
            {
                member = type.GetConstructor(paramType);
            } else {
                member = type.GetMethod(memberName, paramType);
            }
            assert member != null : type + "::" + memberName;
	    break;
	case ModuleRef.ID:
	case MethodDef.ID:
	case TypeSpec.ID:
	    throw new RuntimeException("initCustomAttributes: "
                                       + pefile.getTable(mtbl).getTableName());
	}
	return member;
    }

    protected void initCustomAttributes(Type attributeType) {
        initAttributes(this, definingRow, Table.ModuleDef.ID, attributeType);
    }

    // explicitly only package-visible
    void initAttributes(CustomAttributeProvider cap, int definingRow,
                         int sourceTableId, Type attributeType)
    {
	int parentIndex = Table.encodeIndex(definingRow,
                                            Table._HasCustomAttribute,
                                            sourceTableId);
	Table.CustomAttribute attrs = pefile.CustomAttribute;
	for (int row = 1; row <= attrs.rows; row++) {
            ConstructorInfo attrConstr = null;
	    attrs.readRow(row);
	    if (attrs.Parent == parentIndex) {
		int tableId = Table.getTableId(Table._CustomAttributeType,
					       attrs.Type);
		int ind = Table.getTableIndex(Table._CustomAttributeType,
					      attrs.Type);
		switch (tableId) {
		case MethodDef.ID:
		    attrConstr = (ConstructorInfo)this.getMethod(ind);
		    break;
		case MemberRef.ID:
		    //System.out.println(PEFile.short2hex(ind) + "@MemberRef");
                    Assembly attrAssem =
                        attributeType == null ? null : attributeType.Assembly();
		    MemberInfo mi = this.getMemberRef(ind, attrAssem);
                    if (mi != null) {
                        assert mi instanceof ConstructorInfo
                            : "Expected ConstructorInfo; found " + mi;
                        attrConstr = (ConstructorInfo)mi;
                    }
		    break;
		default:
		    throw new RuntimeException();
		}
                if (attrConstr != null
                    && (attrConstr.DeclaringType == attributeType
                        || attributeType == null))
                    cap.addCustomAttribute(attrConstr, attrs.getValue());
	    }
	}
    }

    //##########################################################################

} // class PEModule

Other Scala examples (source code examples)

Here is a short list of links related to this Scala PEModule.java source code file:



my book on functional programming

 

new blog posts

 

Copyright 1998-2019 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.