} else {
classFile.major = header.getDefaultClassMajorVersion();
classFile.minor = header.getDefaultClassMinorVersion();
}
// build constant pool
ClassConstantPool cp = classFile.pool;
int fullNameIndexInCpClass = classBands.getClassThisInts()[classNum];
String fullName = cpBands.getCpClass()[fullNameIndexInCpClass];
// SourceFile attribute
int i = fullName.lastIndexOf("/") + 1; // if lastIndexOf==-1, then
// -1+1=0, so str.substring(0)
// == str
// Get the source file attribute
ArrayList classAttributes = classBands.getClassAttributes()[classNum];
SourceFileAttribute sourceFileAttribute = null;
for (int index = 0; index < classAttributes.size(); index++) {
if (((Attribute) classAttributes.get(index))
.isSourceFileAttribute()) {
sourceFileAttribute = ((SourceFileAttribute) classAttributes
.get(index));
}
}
if (sourceFileAttribute == null) {
// If we don't have a source file attribute yet, we need
// to infer it from the class.
AttributeLayout SOURCE_FILE = attrDefinitionBands
.getAttributeDefinitionMap().getAttributeLayout(
AttributeLayout.ATTRIBUTE_SOURCE_FILE,
AttributeLayout.CONTEXT_CLASS);
if (SOURCE_FILE.matches(classBands.getRawClassFlags()[classNum])) {
int firstDollar = SegmentUtils.indexOfFirstDollar(fullName);
String fileName = null;
if (firstDollar > -1 && (i <= firstDollar)) {
fileName = fullName.substring(i, firstDollar) + ".java";
} else {
fileName = fullName.substring(i) + ".java";
}
sourceFileAttribute = new SourceFileAttribute(cpBands
.cpUTF8Value(fileName, false));
classFile.attributes = new Attribute[] { (Attribute) cp
.add(sourceFileAttribute) };
} else {
classFile.attributes = new Attribute[] {};
}
} else {
classFile.attributes = new Attribute[] { (Attribute) cp
.add(sourceFileAttribute) };
}
// If we see any class attributes, add them to the class's attributes
// that will
// be written out. Keep SourceFileAttributes out since we just
// did them above.
ArrayList classAttributesWithoutSourceFileAttribute = new ArrayList(classAttributes.size());
for (int index = 0; index < classAttributes.size(); index++) {
Attribute attrib = (Attribute) classAttributes.get(index);
if (!attrib.isSourceFileAttribute()) {
classAttributesWithoutSourceFileAttribute.add(attrib);
}
}
Attribute[] originalAttributes = classFile.attributes;
classFile.attributes = new Attribute[originalAttributes.length
+ classAttributesWithoutSourceFileAttribute.size()];
System.arraycopy(originalAttributes, 0, classFile.attributes, 0,
originalAttributes.length);
for (int index = 0; index < classAttributesWithoutSourceFileAttribute
.size(); index++) {
Attribute attrib = ((Attribute) classAttributesWithoutSourceFileAttribute
.get(index));
cp.add(attrib);
classFile.attributes[originalAttributes.length + index] = attrib;
}
// this/superclass
ClassFileEntry cfThis = cp.add(cpBands.cpClassValue(fullNameIndexInCpClass));
ClassFileEntry cfSuper = cp.add(cpBands.cpClassValue(classBands
.getClassSuperInts()[classNum]));
// add interfaces
ClassFileEntry cfInterfaces[] = new ClassFileEntry[classBands
.getClassInterfacesInts()[classNum].length];
for (i = 0; i < cfInterfaces.length; i++) {
cfInterfaces[i] = cp.add(cpBands.cpClassValue(classBands
.getClassInterfacesInts()[classNum][i]));
}
// add fields
ClassFileEntry cfFields[] = new ClassFileEntry[classBands
.getClassFieldCount()[classNum]];
// fieldDescr and fieldFlags used to create this
for (i = 0; i < cfFields.length; i++) {
int descriptorIndex = classBands.getFieldDescrInts()[classNum][i];
int nameIndex = cpBands.getCpDescriptorNameInts()[descriptorIndex];
int typeIndex = cpBands.getCpDescriptorTypeInts()[descriptorIndex];
CPUTF8 name = cpBands.cpUTF8Value(nameIndex);
CPUTF8 descriptor = cpBands.cpSignatureValue(typeIndex);
cfFields[i] = cp.add(new CPField(name, descriptor, classBands
.getFieldFlags()[classNum][i], classBands
.getFieldAttributes()[classNum][i]));
}
// add methods
ClassFileEntry cfMethods[] = new ClassFileEntry[classBands
.getClassMethodCount()[classNum]];
// methodDescr and methodFlags used to create this
for (i = 0; i < cfMethods.length; i++) {
int descriptorIndex = classBands.getMethodDescrInts()[classNum][i];
// int colon = descriptorStr.indexOf(':');
int nameIndex = cpBands.getCpDescriptorNameInts()[descriptorIndex];
int typeIndex = cpBands.getCpDescriptorTypeInts()[descriptorIndex];
CPUTF8 name = cpBands.cpUTF8Value(nameIndex);
CPUTF8 descriptor = cpBands.cpSignatureValue(typeIndex);
cfMethods[i] = cp.add(new CPMethod(name, descriptor, classBands
.getMethodFlags()[classNum][i], classBands
.getMethodAttributes()[classNum][i]));
}
cp.addNestedEntries();
// add inner class attribute (if required)
boolean addInnerClassesAttr = false;
IcTuple[] ic_local = getClassBands().getIcLocal()[classNum];
boolean ic_local_sent = ic_local != null;
InnerClassesAttribute innerClassesAttribute = new InnerClassesAttribute(
"InnerClasses");
IcTuple[] ic_relevant = getIcBands().getRelevantIcTuples(fullName, cp);
List ic_stored = computeIcStored(ic_local, ic_relevant);
for (int index = 0; index < ic_stored.size(); index++) {
IcTuple icStored = (IcTuple)ic_stored.get(index);
int innerClassIndex = icStored.thisClassIndex();
int outerClassIndex = icStored.outerClassIndex();
int simpleClassNameIndex = icStored.simpleClassNameIndex();
String innerClassString = icStored.thisClassString();
String outerClassString = icStored.outerClassString();
String simpleClassName = icStored.simpleClassName();
CPClass innerClass = null;
CPUTF8 innerName = null;
CPClass outerClass = null;
innerClass = innerClassIndex != -1 ? cpBands
.cpClassValue(innerClassIndex) : cpBands
.cpClassValue(innerClassString);
if (!icStored.isAnonymous()) {
innerName = simpleClassNameIndex != -1 ? cpBands.cpUTF8Value(
simpleClassNameIndex) : cpBands
.cpUTF8Value(simpleClassName);
}
if (icStored.isMember()) {
outerClass = outerClassIndex != -1 ? cpBands
.cpClassValue(outerClassIndex) : cpBands
.cpClassValue(outerClassString);
}
int flags = icStored.F;
innerClassesAttribute.addInnerClassesEntry(innerClass, outerClass,
innerName, flags);
addInnerClassesAttr = true;
}
// If ic_local is sent and it's empty, don't add
// the inner classes attribute.
if (ic_local_sent && (ic_local.length == 0)) {
addInnerClassesAttr = false;
}
// If ic_local is not sent and ic_relevant is empty,
// don't add the inner class attribute.
if (!ic_local_sent && (ic_relevant.length == 0)) {
addInnerClassesAttr = false;
}
if (addInnerClassesAttr) {
// Need to add the InnerClasses attribute to the
// existing classFile attributes.
Attribute[] originalAttrs = classFile.attributes;
Attribute[] newAttrs = new Attribute[originalAttrs.length + 1];
for (int index = 0; index < originalAttrs.length; index++) {
newAttrs[index] = originalAttrs[index];
}
newAttrs[newAttrs.length - 1] = innerClassesAttribute;
classFile.attributes = newAttrs;
cp.addWithNestedEntries(innerClassesAttribute);
}
// sort CP according to cp_All
cp.resolve(this);
// NOTE the indexOf is only valid after the cp.resolve()
// build up remainder of file
classFile.accessFlags = (int) classBands.getClassFlags()[classNum];
classFile.thisClass = cp.indexOf(cfThis);
classFile.superClass = cp.indexOf(cfSuper);
// TODO placate format of file for writing purposes
classFile.interfaces = new int[cfInterfaces.length];
for (i = 0; i < cfInterfaces.length; i++) {
classFile.interfaces[i] = cp.indexOf(cfInterfaces[i]);
}
classFile.fields = cfFields;
classFile.methods = cfMethods;
return classFile;
}