in modules/pack200/src/main/java/org/apache/harmony/unpack200/ClassBands.java [479:725]
private void parseClassAttrBands(InputStream in) throws IOException,
Pack200Exception {
String[] cpUTF8 = cpBands.getCpUTF8();
String[] cpClass = cpBands.getCpClass();
// Prepare empty attribute lists
classAttributes = new ArrayList[classCount];
for (int i = 0; i < classCount; i++) {
classAttributes[i] = new ArrayList();
}
classFlags = parseFlags("class_flags", in, classCount, Codec.UNSIGNED5,
options.hasClassFlagsHi());
int classAttrCount = SegmentUtils.countBit16(classFlags);
int[] classAttrCounts = decodeBandInt("class_attr_count", in,
Codec.UNSIGNED5, classAttrCount);
int[][] classAttrIndexes = decodeBandInt("class_attr_indexes", in,
Codec.UNSIGNED5, classAttrCounts);
int callCount = getCallCount(classAttrIndexes,
new long[][] { classFlags }, AttributeLayout.CONTEXT_CLASS);
int[] classAttrCalls = decodeBandInt("class_attr_calls", in,
Codec.UNSIGNED5, callCount);
AttributeLayout deprecatedLayout = attrMap.getAttributeLayout(
AttributeLayout.ATTRIBUTE_DEPRECATED,
AttributeLayout.CONTEXT_CLASS);
AttributeLayout sourceFileLayout = attrMap.getAttributeLayout(
AttributeLayout.ATTRIBUTE_SOURCE_FILE,
AttributeLayout.CONTEXT_CLASS);
int sourceFileCount = SegmentUtils.countMatches(classFlags,
sourceFileLayout);
int[] classSourceFile = decodeBandInt("class_SourceFile_RUN", in,
Codec.UNSIGNED5, sourceFileCount);
AttributeLayout enclosingMethodLayout = attrMap.getAttributeLayout(
AttributeLayout.ATTRIBUTE_ENCLOSING_METHOD,
AttributeLayout.CONTEXT_CLASS);
int enclosingMethodCount = SegmentUtils.countMatches(classFlags,
enclosingMethodLayout);
int[] enclosingMethodRC = decodeBandInt(
"class_EnclosingMethod_RC", in, Codec.UNSIGNED5,
enclosingMethodCount);
int[] enclosingMethodRDN = decodeBandInt(
"class_EnclosingMethod_RDN", in, Codec.UNSIGNED5,
enclosingMethodCount);
AttributeLayout signatureLayout = attrMap.getAttributeLayout(
AttributeLayout.ATTRIBUTE_SIGNATURE,
AttributeLayout.CONTEXT_CLASS);
int signatureCount = SegmentUtils.countMatches(classFlags,
signatureLayout);
int[] classSignature = decodeBandInt("class_Signature_RS", in,
Codec.UNSIGNED5, signatureCount);
int backwardsCallsUsed = parseClassMetadataBands(in, classAttrCalls);
AttributeLayout innerClassLayout = attrMap.getAttributeLayout(
AttributeLayout.ATTRIBUTE_INNER_CLASSES,
AttributeLayout.CONTEXT_CLASS);
int innerClassCount = SegmentUtils.countMatches(classFlags,
innerClassLayout);
int[] classInnerClassesN = decodeBandInt("class_InnerClasses_N", in,
Codec.UNSIGNED5, innerClassCount);
int[][] classInnerClassesRC = decodeBandInt("class_InnerClasses_RC",
in, Codec.UNSIGNED5, classInnerClassesN);
int[][] classInnerClassesF = decodeBandInt("class_InnerClasses_F", in,
Codec.UNSIGNED5, classInnerClassesN);
int flagsCount = 0;
for (int i = 0; i < classInnerClassesF.length; i++) {
for (int j = 0; j < classInnerClassesF[i].length; j++) {
if (classInnerClassesF[i][j] != 0) {
flagsCount++;
}
}
}
int[] classInnerClassesOuterRCN = decodeBandInt(
"class_InnerClasses_outer_RCN", in, Codec.UNSIGNED5, flagsCount);
int[] classInnerClassesNameRUN = decodeBandInt(
"class_InnerClasses_name_RUN", in, Codec.UNSIGNED5, flagsCount);
AttributeLayout versionLayout = attrMap.getAttributeLayout(
AttributeLayout.ATTRIBUTE_CLASS_FILE_VERSION,
AttributeLayout.CONTEXT_CLASS);
int versionCount = SegmentUtils.countMatches(classFlags, versionLayout);
int[] classFileVersionMinorH = decodeBandInt(
"class_file_version_minor_H", in, Codec.UNSIGNED5, versionCount);
int[] classFileVersionMajorH = decodeBandInt(
"class_file_version_major_H", in, Codec.UNSIGNED5, versionCount);
if (versionCount > 0) {
classVersionMajor = new int[classCount];
classVersionMinor = new int[classCount];
}
int defaultVersionMajor = header.getDefaultClassMajorVersion();
int defaultVersionMinor = header.getDefaultClassMinorVersion();
// Parse non-predefined attribute bands
int backwardsCallIndex = backwardsCallsUsed;
int limit = options.hasClassFlagsHi() ? 62 : 31;
AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
int[] counts = new int[limit + 1];
List[] otherAttributes = new List[limit + 1];
for (int i = 0; i < limit; i++) {
AttributeLayout layout = attrMap.getAttributeLayout(i,
AttributeLayout.CONTEXT_CLASS);
if (layout != null && !(layout.isDefaultLayout())) {
otherLayouts[i] = layout;
counts[i] = SegmentUtils.countMatches(classFlags, layout);
}
}
for (int i = 0; i < counts.length; i++) {
if (counts[i] > 0) {
NewAttributeBands bands = attrMap
.getAttributeBands(otherLayouts[i]);
otherAttributes[i] = bands.parseAttributes(in, counts[i]);
int numBackwardsCallables = otherLayouts[i]
.numBackwardsCallables();
if (numBackwardsCallables > 0) {
int[] backwardsCalls = new int[numBackwardsCallables];
System.arraycopy(classAttrCalls, backwardsCallIndex,
backwardsCalls, 0, numBackwardsCallables);
bands.setBackwardsCalls(backwardsCalls);
backwardsCallIndex += numBackwardsCallables;
}
}
}
// Now process the attribute bands we have parsed
int sourceFileIndex = 0;
int enclosingMethodIndex = 0;
int signatureIndex = 0;
int innerClassIndex = 0;
int innerClassC2NIndex = 0;
int versionIndex = 0;
icLocal = new IcTuple[classCount][];
for (int i = 0; i < classCount; i++) {
long flag = classFlags[i];
if (deprecatedLayout.matches(classFlags[i])) {
classAttributes[i].add(new DeprecatedAttribute());
}
if (sourceFileLayout.matches(flag)) {
long result = classSourceFile[sourceFileIndex];
ClassFileEntry value = sourceFileLayout.getValue(result,
cpBands.getConstantPool());
if (value == null) {
// Remove package prefix
String className = classThis[i].substring(classThis[i]
.lastIndexOf('/') + 1);
className = className
.substring(className.lastIndexOf('.') + 1);
// Remove mangled nested class names
char[] chars = className.toCharArray();
int index = -1;
for (int j = 0; j < chars.length; j++) {
if (chars[j] <= 0x2D) {
index = j;
break;
}
}
if (index > -1) {
className = className.substring(0, index);
}
// Add .java to the end
value = cpBands.cpUTF8Value(className + ".java", true);
}
classAttributes[i].add(new SourceFileAttribute((CPUTF8)value));
sourceFileIndex++;
}
if (enclosingMethodLayout.matches(flag)) {
CPClass theClass = cpBands
.cpClassValue(enclosingMethodRC[enclosingMethodIndex]);
CPNameAndType theMethod = null;
if(enclosingMethodRDN[enclosingMethodIndex] != 0) {
theMethod = cpBands
.cpNameAndTypeValue(enclosingMethodRDN[enclosingMethodIndex] - 1);
}
classAttributes[i].add(new EnclosingMethodAttribute(theClass,
theMethod));
enclosingMethodIndex++;
}
if (signatureLayout.matches(flag)) {
long result = classSignature[signatureIndex];
CPUTF8 value = (CPUTF8) signatureLayout.getValue(result, cpBands
.getConstantPool());
classAttributes[i].add(new SignatureAttribute(value));
signatureIndex++;
}
if (innerClassLayout.matches(flag)) {
// Just create the tuples for now because the attributes are
// decided at the end when creating class constant pools
icLocal[i] = new IcTuple[classInnerClassesN[innerClassIndex]];
for (int j = 0; j < icLocal[i].length; j++) {
int icTupleCIndex = classInnerClassesRC[innerClassIndex][j];
int icTupleC2Index = -1;
int icTupleNIndex = -1;
String icTupleC = cpClass[icTupleCIndex];
int icTupleF = classInnerClassesF[innerClassIndex][j];
String icTupleC2 = null;
String icTupleN = null;
if (icTupleF != 0) {
icTupleC2Index = classInnerClassesOuterRCN[innerClassC2NIndex];
icTupleNIndex = classInnerClassesNameRUN[innerClassC2NIndex];
icTupleC2 = cpClass[icTupleC2Index];
icTupleN = cpUTF8[icTupleNIndex];
innerClassC2NIndex++;
} else {
// Get from icBands
IcBands icBands = segment.getIcBands();
IcTuple[] icAll = icBands.getIcTuples();
for (int k = 0; k < icAll.length; k++) {
if (icAll[k].getC().equals(icTupleC)) {
icTupleF = icAll[k].getF();
icTupleC2 = icAll[k].getC2();
icTupleN = icAll[k].getN();
break;
}
}
}
IcTuple icTuple = new IcTuple(icTupleC, icTupleF,
icTupleC2, icTupleN, icTupleCIndex, icTupleC2Index, icTupleNIndex, j);
icLocal[i][j] = icTuple;
}
innerClassIndex++;
}
if (versionLayout.matches(flag)) {
classVersionMajor[i] = classFileVersionMajorH[versionIndex];
classVersionMinor[i] = classFileVersionMinorH[versionIndex];
versionIndex++;
} else if (classVersionMajor != null) {
// Fill in with defaults
classVersionMajor[i] = defaultVersionMajor;
classVersionMinor[i] = defaultVersionMinor;
}
// Non-predefined attributes
for (int j = 0; j < otherLayouts.length; j++) {
if (otherLayouts[j] != null && otherLayouts[j].matches(flag)) {
// Add the next attribute
classAttributes[i].add(otherAttributes[j].get(0));
otherAttributes[j].remove(0);
}
}
}
}