blob: fdc80aa9a0da1ce51ae4314e1da5b14a153259bb [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2004, 2010 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute and Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* $Id: ClassAttributeReader.java 23492 2010-02-05 22:57:56Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Fraunhofer FIRST - Initial API and implementation
* Technical University Berlin - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otdt.debug.tests;
import java.io.IOException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.ClassFormatException;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Unknown;
import org.eclipse.core.runtime.IPath;
/**
* @author ike
*
* Read class file(s) and display its Attributes. Copied and modified from
* otlistclass.
*
* $Id: ClassAttributeReader.java 23492 2010-02-05 22:57:56Z stephan $
*/
public class ClassAttributeReader
{
static boolean printCompilerAttributes = false;
private JavaClass _javaclass;
private Hashtable _classAttributes = new Hashtable();
private Hashtable _methodAttributes = new Hashtable();
private String _error;
public ClassAttributeReader(IPath classFilePath)
{
try {
_javaclass = new ClassParser(classFilePath.toOSString()).parse(); // May throw
readAndStoreAttributes();
}
catch (ClassFormatError e)
{
_error = e.getMessage();
e.printStackTrace();
}
catch (IOException e)
{
_error = e.getMessage();
e.printStackTrace();
} catch (ClassFormatException e) {
_error = e.getMessage();
e.printStackTrace();
}
}
public String getError()
{
return _error;
}
public boolean isSDEAvailable()
{
return _classAttributes.containsKey("SourceDebugExtension");
}
public char[] getSDE()
{
String[] sdeAsString = (String[]) _classAttributes.get("SourceDebugExtension");
if (sdeAsString != null && sdeAsString[0] != null)
{
return sdeAsString[0].toCharArray();
}
return null;
}
public boolean isClassAttributeAvailable(String attributeName)
{
return _classAttributes.containsKey(attributeName);
}
public String[] getClassAttributeValues(String attributeName)
{
if (isClassAttributeAvailable(attributeName))
return (String[])_classAttributes.get(attributeName);
return null;
}
public void readAndStoreAttributes()
{
Attribute[] attributesAsArray = _javaclass.getAttributes();
ConstantPool cp = _javaclass.getConstantPool();
String class_name = _javaclass.getClassName();
Vector values;
for (int k = 0; k < attributesAsArray.length; k++)
{
Attribute actAttr = attributesAsArray[k];
Unknown attr = isOTAttribute(actAttr);
if (attr != null)
{ //this is a callin attribute
String attrName = attr.getName();
byte[] indizes = attr.getBytes();
int count = combineTwoBytes(indizes, 0);
int numberOfEntries = 0;
String[] names;
values = new Vector();
if (attrName.equals("OTClassFlags"))
{
int classFlags = combineTwoBytes(indizes, 0);
String flagsString = "";
if ((classFlags & 1) != 0)
flagsString += "team ";
if ((classFlags & 2) != 0)
flagsString += "role";
if ((classFlags & 4) != 0)
flagsString += "role-local"; // relevant for the
// compiler only.
values.add(new String[]{flagsString});
}
else if (attrName.equals("CallinRoleBaseBindings"))
{
numberOfEntries = 2;
int i = 2;
while (i <= 2 * count * numberOfEntries)
{
names = new String[numberOfEntries];
i = scanStrings(names, indizes, i, cp);
String role_name = names[0];
String base_name = names[1];
values.add(new String[] { role_name, base_name });
}
}
else if (attrName.equals("CallinMethodMappings"))
{
numberOfEntries = 5;
int i = 2;
for (int n = 0; n < count; n++)
{
names = new String[numberOfEntries];
i = scanStrings(names, indizes, i, cp);
String wrapper_name = null;
String wrapper_signature = null;
int index = 0;
String binding_label = names[index++];
String role_method_name = names[index++];
String role_method_signature = names[index++];
String real_role_return = names[index++];
String binding_modifier = names[index++];
int base_len = combineTwoBytes(indizes, i);
i += 2;
names = new String[4];
for (int n_base = 0; n_base < base_len; n_base++)
{
i = scanStrings(names, indizes, i, cp);
String base_method_name = names[0];
String base_method_signature = names[1];
wrapper_name = names[2];
wrapper_signature = names[3];
values.add(new String[] { binding_label, role_method_name,
role_method_signature, real_role_return,
binding_modifier, base_method_name,
base_method_signature, wrapper_name,
wrapper_signature});
}
}
}
else if (attrName.equals("CalloutBoundFields"))
{
numberOfEntries = 2;
int i = 2;
for (int n = 0; n < count; n++)
{
names = new String[numberOfEntries];
i = scanStrings(names, indizes, i, cp);
String fieldName = names[0];
String fieldType = names[1];
int flags = combineTwoBytes(indizes, i);
String flagString = (flags & 1) == 1 ? "set " : "get ";
if ((flags & 2) != 0)
flagString = flagString + "static ";
i += 2;
values.add(new String[]{flagString, fieldType, fieldName});
}
}
else if (attrName.equals("InaccessibleBaseMethods"))
{
numberOfEntries = 3;
int i = 2;
while (i <= 2 * count * numberOfEntries)
{
names = new String[numberOfEntries];
i = scanStrings(names, indizes, i, cp);
String base_class = names[0];
String base_method = names[1];
String base_signature = names[2];
values.add(new String[]{base_class, base_method, base_signature});
}
}
else if (attrName.equals("ReferencedTeams"))
{
numberOfEntries = 1;
int i = 2;
while (i <= 2 * count * numberOfEntries)
{
names = new String[numberOfEntries];
i = scanStrings(names, indizes, i, cp);
String referenced_team = names[0];
values.add(new String[]{referenced_team});
}
}
else if (attrName.equals("BaseClassTags"))
{
numberOfEntries = 2;
String baseClass = "";
int tag = 0;
HashMap tagMap = new HashMap();
int i = 2;
while (i <= 2 * count * numberOfEntries)
{
for (int j = 0; j < numberOfEntries; j++)
{
int nextIndex = combineTwoBytes(indizes, i);
if (j == 0)
{
ConstantUtf8 cons = (ConstantUtf8) cp
.getConstant(nextIndex);
baseClass = cons.getBytes();
}
else if (j == 1)
{
tag = nextIndex;
}
i += 2;
}
tagMap.put(baseClass, new Integer(tag));
values.add(new String[]{class_name, baseClass, String.valueOf(tag)});
}
}
else if (attrName.equals("PlayedBy"))
{
names = new String[1];
scanStrings(names, indizes, 0, cp);
String base_class_name = names[0];
values.add(new String[]{base_class_name});
}
else if (attrName.equals("OTCompilerVersion"))
{
int encodedVersion = combineTwoBytes(indizes, 0);
int major = encodedVersion >>> 9;
int minor = (encodedVersion >>> 5) & 0xF;
int revision = encodedVersion & 0x1F;
values.add(new String[]{String.valueOf(major), String.valueOf(minor), String.valueOf(revision)});
}
else if (attrName.equals("CallinPrecedence"))
{
List precedenceList = new LinkedList();
numberOfEntries = 1;
int i = 2;
while (i <= 2 * count * numberOfEntries)
{
names = new String[numberOfEntries];
i = scanStrings(names, indizes, i, cp);
String binding_label = names[0];
precedenceList.add(binding_label);
}
values.add(new String[]{precedenceList.toString()});
} // ==== Following: attributes relevant for the compiler only:
// ====
else if (attrName.equals("RoleFiles"))
{
numberOfEntries = 1;
int i = 2;
while (i <= 2 * count * numberOfEntries)
{
names = new String[numberOfEntries];
i = scanStrings(names, indizes, i, cp);
String roleFile = names[0];
values.add(new String[]{roleFile});
}
}
else if (attrName.equals("CalloutMethodMappings"))
{
numberOfEntries = 2;
int i = 2;
for (int n = 0; n < count; n++)
{
names = new String[numberOfEntries];
i = scanStrings(names, indizes, i, cp);
int index = 0;
String role_method_name = names[index++];
String role_method_signature = names[index++];
values.add(new String[]{role_method_name, role_method_signature});
}
}
else if (attrName.equals("SourceDebugExtension"))
{
String smap = new String();
for (int idx = 0; idx < indizes.length; idx++)
{
smap += String.valueOf((char) indizes[idx]);
}
values.add(new String[]{smap});
}
_classAttributes.put(attrName, values);
}
}
Method[] possibleRoleMethods = _javaclass.getMethods();
for (int i = 0; i < possibleRoleMethods.length; i++)
{
Method meth = possibleRoleMethods[i];
Attribute[] attrsMethod = meth.getAttributes();
String method_name = meth.getName();
//TODO(ike): handle and store attributes of methodes also
// scanMethodOTAttributes(attrsMethod, class_name, method_name, cp);
}
}
Unknown isOTAttribute(Attribute attr)
{
if (attr instanceof Unknown)
{
Unknown unknown = (Unknown) attr;
String attrName = unknown.getName();
if (attrName.equals("CallinRoleBaseBindings")
|| attrName.equals("CallinMethodMappings")
|| attrName.equals("CallinParamMappings")
|| attrName.equals("CallinFlags")
|| attrName.equals("CalloutBoundFields")
|| attrName.equals("WrappedRoleSignature")
|| attrName.equals("WrappedBaseSignature")
|| attrName.equals("InaccessibleBaseMethods")
|| attrName.equals("ReferencedTeams")
|| attrName.equals("BaseClassTags")
|| attrName.equals("PlayedBy")
|| attrName.equals("Modifiers")
|| attrName.equals("OTCompilerVersion")
|| attrName.equals("OTClassFlags")
|| attrName.equals("CallinPrecedence")
|| attrName.equals("SourceDebugExtension"))
{
return unknown;
}
if (printCompilerAttributes)
{
if (attrName.equals("RoleFiles")
|| attrName.equals("CalloutMethodMappings")
|| attrName.equals("Modifiers")
|| attrName.equals("CopyInheritanceSrc"))
{
return unknown;
}
}
}
return null;
}
/**
* combines two int's representing the higher and the lower part of a two
* byte number.
*
* @param first
* the first (higer?) byte
* @param second
* the second (lower?) byte
* @return the combined number
*/
int combineTwoBytes(byte[] indizes, int start)
{
int first = indizes[start];
int second = indizes[start + 1];
int twoBytes = 0;
twoBytes = twoBytes | (first & 0xff);
twoBytes = twoBytes << 8;
twoBytes = twoBytes | (second & 0xff);
return twoBytes;
}
/**
* Read some strings from a byte array.
*
* @param entries
* Result array to be provided by caller.
* @param indizes
* buffer of read bytes to be provided by caller, consists if
* indizes into the constant pool
* @param i
* current index into indizes
* @param cp
* the pool.
* @result updated value of <tt>i</tt>.
*/
int scanStrings(String[] entries, byte[] indizes, int i, ConstantPool cp)
{
for (int j = 0; j < entries.length; j++)
{
int nextIndex = combineTwoBytes(indizes, i);
ConstantUtf8 cons = (ConstantUtf8) cp.getConstant(nextIndex);
String content = cons.getBytes();
entries[j] = content;
i += 2;
}
return i;
}
void scanMethodOTAttributes(Attribute[] attributes, String class_name,
String method_name, ConstantPool cp)
{
Vector methodAttributesValues = new Vector();
boolean ot_attribute_found = false;
for (int k = 0; k < attributes.length; k++)
{
Attribute actAttr = attributes[k];
Unknown attr = isOTAttribute(actAttr);
if (attr != null)
{ //this is an OT attribute
if (ot_attribute_found == false)
{
System.out.println();
System.out.println("--- in method '" + method_name
+ "': ---");
ot_attribute_found = true;
}
String attrName = attr.getName();
if (attrName.equals("CallinParamMappings"))
{
System.out.println("CallinParamMappings:");
byte[] indizes = attr.getBytes();
int[] positions = null;
if (indizes == null)
throw new RuntimeException("Unexpected null attr");
int count = combineTwoBytes(indizes, 0);
positions = new int[count];
int p = 2;
for (int i = 0; i < count; i++, p += 2)
{
positions[i] = combineTwoBytes(indizes, p);
System.out.println("\t" + i + " <- " + positions[i]);
}
}
else if (attrName.equals("WrappedRoleSignature"))
{
System.out.println("WrappedRoleSignature:");
byte[] indizes = attr.getBytes();
String[] names = new String[1];
scanStrings(names, indizes, 0, cp);
String role_signature = names[0];
System.out.println("\t" + role_signature);
}
else if (attrName.equals("WrappedBaseSignature"))
{
System.out.println("WrappedBaseSignature:");
byte[] indizes = attr.getBytes();
String[] names = new String[1];
scanStrings(names, indizes, 0, cp);
String base_signature = names[0];
System.out.println("\t" + base_signature);
}
else if (attrName.equals("CallinFlags"))
{
System.out.print("CallinFlags: ");
byte[] bytes = attr.getBytes();
int flags = combineTwoBytes(bytes, 0);
if ((flags & 1) != 0)
System.out.print("OVERRIDE ");
if ((flags & 2) != 0)
System.out.print("WRAPPER ");
if ((flags & 4) != 0)
System.out.print("REPLACE ");
System.out.println();
} // ==== Following: attributes relevant for the compiler only:
// ====
else if (attrName.equals("Modifiers"))
{
System.out.print("Modifiers: 0x");
byte[] bytes = attr.getBytes();
int flags = combineTwoBytes(bytes, 0);
System.out.println(Integer.toHexString(flags));
}
else if (attrName.equals("CopyInheritanceSrc"))
{
System.out.println("CopyInheritanceSrc:");
byte[] indizes = attr.getBytes();
String[] names = new String[1];
scanStrings(names, indizes, 0, cp);
String src_name = names[0];
System.out.println("\t" + src_name);
}
}
}
}
}