0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: package org.apache.harmony.pack200;
0018:
0019: import java.io.IOException;
0020: import java.io.InputStream;
0021: import java.util.ArrayList;
0022: import java.util.Iterator;
0023: import java.util.List;
0024:
0025: import org.apache.harmony.pack200.bytecode.Attribute;
0026: import org.apache.harmony.pack200.bytecode.CPClass;
0027: import org.apache.harmony.pack200.bytecode.CPNameAndType;
0028: import org.apache.harmony.pack200.bytecode.CPUTF8;
0029: import org.apache.harmony.pack200.bytecode.ClassConstantPool;
0030: import org.apache.harmony.pack200.bytecode.ConstantValueAttribute;
0031: import org.apache.harmony.pack200.bytecode.EnclosingMethodAttribute;
0032: import org.apache.harmony.pack200.bytecode.ExceptionsAttribute;
0033: import org.apache.harmony.pack200.bytecode.LineNumberTableAttribute;
0034: import org.apache.harmony.pack200.bytecode.LocalVariableTableAttribute;
0035: import org.apache.harmony.pack200.bytecode.LocalVariableTypeTableAttribute;
0036: import org.apache.harmony.pack200.bytecode.SignatureAttribute;
0037: import org.apache.harmony.pack200.bytecode.SourceFileAttribute;
0038:
0039: /**
0040: * Pack200 Class Bands
0041: */
0042: public class ClassBands extends BandSet {
0043:
0044: private int[] classFieldCount;
0045:
0046: private long[] classFlags;
0047:
0048: private String[][] classInterfaces;
0049:
0050: private int[] classMethodCount;
0051:
0052: private String[] classSuper;
0053:
0054: private String[] classThis;
0055:
0056: private ArrayList[] classAttributes;
0057:
0058: private int[] classVersionMajor;
0059:
0060: private int[] classVersionMinor;
0061:
0062: private IcTuple[][] icLocal;
0063:
0064: private ArrayList[] codeAttributes;
0065:
0066: private int[] codeHandlerCount;
0067:
0068: private int[] codeMaxNALocals;
0069:
0070: private int[] codeMaxStack;
0071:
0072: private ArrayList[][] fieldAttributes;
0073:
0074: private String[][] fieldDescr;
0075:
0076: private long[][] fieldFlags;
0077:
0078: private ArrayList[][] methodAttributes;
0079:
0080: private String[][] methodDescr;
0081:
0082: private long[][] methodFlags;
0083:
0084: private AttributeLayoutMap attrMap;
0085:
0086: private CpBands cpBands;
0087:
0088: private SegmentOptions options;
0089:
0090: private int classCount;
0091:
0092: private int[] methodAttrCalls;
0093:
0094: private int[][] codeHandlerStartP;
0095:
0096: private int[][] codeHandlerEndPO;
0097:
0098: private int[][] codeHandlerCatchPO;
0099:
0100: private String[][] codeHandlerClassRCN;
0101:
0102: /**
0103: * @param segment
0104: */
0105: public ClassBands(Segment segment) {
0106: super (segment);
0107: this .attrMap = segment.getAttrDefinitionBands()
0108: .getAttributeDefinitionMap();
0109: this .cpBands = segment.getCpBands();
0110: this .classCount = header.getClassCount();
0111: this .options = header.getOptions();
0112:
0113: }
0114:
0115: /*
0116: * (non-Javadoc)
0117: *
0118: * @see org.apache.harmony.pack200.BandSet#unpack(java.io.InputStream)
0119: */
0120: public void unpack(InputStream in) throws IOException,
0121: Pack200Exception {
0122: int classCount = header.getClassCount();
0123: classThis = parseReferences("class_this", in, Codec.DELTA5,
0124: classCount, cpBands.getCpClass());
0125: classSuper = parseReferences("class_super", in, Codec.DELTA5,
0126: classCount, cpBands.getCpClass());
0127: int[] classInterfaceLengths = decodeBandInt(
0128: "class_interface_count", in, Codec.DELTA5, classCount);
0129: classInterfaces = parseReferences("class_interface", in,
0130: Codec.DELTA5, classInterfaceLengths, cpBands
0131: .getCpClass());
0132: classFieldCount = decodeBandInt("class_field_count", in,
0133: Codec.DELTA5, classCount);
0134: classMethodCount = decodeBandInt("class_method_count", in,
0135: Codec.DELTA5, classCount);
0136: parseFieldBands(in);
0137: parseMethodBands(in);
0138: parseClassAttrBands(in);
0139: parseCodeBands(in);
0140:
0141: }
0142:
0143: private void parseFieldBands(InputStream in) throws IOException,
0144: Pack200Exception {
0145: fieldDescr = parseReferences("field_descr", in, Codec.DELTA5,
0146: classFieldCount, cpBands.getCpDescriptor());
0147: parseFieldAttrBands(in);
0148: }
0149:
0150: private void parseFieldAttrBands(InputStream in)
0151: throws IOException, Pack200Exception {
0152: fieldFlags = parseFlags("field_flags", in, classFieldCount,
0153: Codec.UNSIGNED5, options.hasFieldFlagsHi());
0154: int fieldAttrCount = SegmentUtils.countBit16(fieldFlags);
0155: int[] fieldAttrCounts = decodeBandInt("field_attr_count", in,
0156: Codec.UNSIGNED5, fieldAttrCount);
0157: int[][] fieldAttrIndexes = decodeBandInt("field_attr_indexes",
0158: in, Codec.UNSIGNED5, fieldAttrCounts);
0159: int callCount = getCallCount(fieldAttrIndexes, fieldFlags,
0160: AttributeLayout.CONTEXT_FIELD);
0161: int[] fieldAttrCalls = decodeBandInt("field_attr_calls", in,
0162: Codec.UNSIGNED5, callCount);
0163:
0164: // Assign empty field attributes
0165: fieldAttributes = new ArrayList[classCount][];
0166: for (int i = 0; i < classCount; i++) {
0167: fieldAttributes[i] = new ArrayList[fieldFlags[i].length];
0168: for (int j = 0; j < fieldFlags[i].length; j++) {
0169: fieldAttributes[i][j] = new ArrayList();
0170: }
0171: }
0172:
0173: AttributeLayout constantValueLayout = attrMap
0174: .getAttributeLayout("ConstantValue",
0175: AttributeLayout.CONTEXT_FIELD);
0176: int constantCount = SegmentUtils.countMatches(fieldFlags,
0177: constantValueLayout);
0178: int[] field_constantValue_KQ = decodeBandInt(
0179: "field_ConstantValue_KQ", in, Codec.UNSIGNED5,
0180: constantCount);
0181: int constantValueIndex = 0;
0182:
0183: AttributeLayout signatureLayout = attrMap.getAttributeLayout(
0184: AttributeLayout.ATTRIBUTE_SIGNATURE,
0185: AttributeLayout.CONTEXT_FIELD);
0186: int signatureCount = SegmentUtils.countMatches(fieldFlags,
0187: signatureLayout);
0188: int[] fieldSignatureRS = decodeBandInt("field_Signature_RS",
0189: in, Codec.UNSIGNED5, signatureCount);
0190: int signatureIndex = 0;
0191:
0192: int backwardsCallsUsed = parseFieldMetadataBands(in,
0193: fieldAttrCalls);
0194:
0195: // Parse non-predefined attribute bands
0196: int backwardsCallIndex = backwardsCallsUsed;
0197: int limit = options.hasFieldFlagsHi() ? 62 : 31;
0198: AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
0199: int[] counts = new int[limit + 1];
0200: List[] otherAttributes = new List[limit + 1];
0201: for (int i = 0; i < limit; i++) {
0202: AttributeLayout layout = attrMap.getAttributeLayout(i,
0203: AttributeLayout.CONTEXT_FIELD);
0204: if (layout != null && !(layout.isDefaultLayout())) {
0205: otherLayouts[i] = layout;
0206: counts[i] = SegmentUtils.countMatches(fieldFlags,
0207: layout);
0208: }
0209: }
0210: for (int i = 0; i < counts.length; i++) {
0211: if (counts[i] > 0) {
0212: NewAttributeBands bands = attrMap
0213: .getAttributeBands(otherLayouts[i]);
0214: otherAttributes[i] = bands.parseAttributes(in,
0215: counts[i]);
0216: int numBackwardsCallables = otherLayouts[i]
0217: .numBackwardsCallables();
0218: if (numBackwardsCallables > 0) {
0219: int[] backwardsCalls = new int[numBackwardsCallables];
0220: System.arraycopy(fieldAttrCalls,
0221: backwardsCallIndex, backwardsCalls, 0,
0222: numBackwardsCallables);
0223: bands.setBackwardsCalls(backwardsCalls);
0224: backwardsCallIndex += numBackwardsCallables;
0225: }
0226: }
0227: }
0228:
0229: for (int i = 0; i < classCount; i++) {
0230: for (int j = 0; j < fieldFlags[i].length; j++) {
0231: long flag = fieldFlags[i][j];
0232: if (constantValueLayout.matches(flag)) {
0233: // we've got a value to read
0234: long result = field_constantValue_KQ[constantValueIndex];
0235: String desc = fieldDescr[i][j];
0236: int colon = desc.indexOf(':');
0237: String type = desc.substring(colon + 1);
0238: if (type.equals("B") || type.equals("S")
0239: || type.equals("C") || type.equals("Z"))
0240: type = "I";
0241: Object value = constantValueLayout.getValue(result,
0242: type, cpBands.getConstantPool());
0243: fieldAttributes[i][j]
0244: .add(new ConstantValueAttribute(value));
0245: constantValueIndex++;
0246: }
0247: if (signatureLayout.matches(flag)) {
0248: // we've got a signature attribute
0249: long result = fieldSignatureRS[signatureIndex];
0250: String desc = fieldDescr[i][j];
0251: int colon = desc.indexOf(':');
0252: String type = desc.substring(colon + 1);
0253: CPUTF8 value = new CPUTF8((String) signatureLayout
0254: .getValue(result, type, cpBands
0255: .getConstantPool()),
0256: ClassConstantPool.DOMAIN_SIGNATUREASCIIZ);
0257: fieldAttributes[i][j].add(new SignatureAttribute(
0258: value));
0259: signatureIndex++;
0260: }
0261: // Non-predefined attributes
0262: for (int k = 0; k < otherLayouts.length; k++) {
0263: if (otherLayouts[k] != null
0264: && otherLayouts[k].matches(flag)) {
0265: // Add the next attribute
0266: fieldAttributes[i][j].add(otherAttributes[k]
0267: .get(0));
0268: otherAttributes[k].remove(0);
0269: }
0270: }
0271: }
0272: }
0273: }
0274:
0275: private void parseMethodBands(InputStream in) throws IOException,
0276: Pack200Exception {
0277: methodDescr = parseReferences("method_descr", in,
0278: Codec.MDELTA5, classMethodCount, cpBands
0279: .getCpDescriptor());
0280: parseMethodAttrBands(in);
0281: }
0282:
0283: private void parseMethodAttrBands(InputStream in)
0284: throws IOException, Pack200Exception {
0285: methodFlags = parseFlags("method_flags", in, classMethodCount,
0286: Codec.UNSIGNED5, options.hasMethodFlagsHi());
0287: int methodAttrCount = SegmentUtils.countBit16(methodFlags);
0288: int[] methodAttrCounts = decodeBandInt("method_attr_count", in,
0289: Codec.UNSIGNED5, methodAttrCount);
0290: int[][] methodAttrIndexes = decodeBandInt(
0291: "method_attr_indexes", in, Codec.UNSIGNED5,
0292: methodAttrCounts);
0293: int callCount = getCallCount(methodAttrIndexes, methodFlags,
0294: AttributeLayout.CONTEXT_METHOD);
0295: methodAttrCalls = decodeBandInt("code_attr_calls", in,
0296: Codec.UNSIGNED5, callCount);
0297:
0298: // assign empty method attributes
0299: methodAttributes = new ArrayList[classCount][];
0300: for (int i = 0; i < classCount; i++) {
0301: methodAttributes[i] = new ArrayList[methodFlags[i].length];
0302: for (int j = 0; j < methodFlags[i].length; j++) {
0303: methodAttributes[i][j] = new ArrayList();
0304: }
0305: }
0306:
0307: // Parse method exceptions attributes
0308: AttributeLayout methodExceptionsLayout = attrMap
0309: .getAttributeLayout(
0310: AttributeLayout.ATTRIBUTE_EXCEPTIONS,
0311: AttributeLayout.CONTEXT_METHOD);
0312: int count = SegmentUtils.countMatches(methodFlags,
0313: methodExceptionsLayout);
0314: int[] numExceptions = decodeBandInt("method_Exceptions_n", in,
0315: Codec.UNSIGNED5, count);
0316: String[][] methodExceptionsRS = parseReferences(
0317: "method_Exceptions_RC", in, Codec.UNSIGNED5,
0318: numExceptions, cpBands.getCpClass());
0319:
0320: // Parse method signature attributes
0321: AttributeLayout methodSignatureLayout = attrMap
0322: .getAttributeLayout(
0323: AttributeLayout.ATTRIBUTE_SIGNATURE,
0324: AttributeLayout.CONTEXT_METHOD);
0325: int count1 = SegmentUtils.countMatches(methodFlags,
0326: methodSignatureLayout);
0327: long[] methodSignatureRS = decodeBandLong(
0328: "method_signature_RS", in, Codec.UNSIGNED5, count1);
0329:
0330: // Parse method metadata bands
0331: int backwardsCallsUsed = parseMethodMetadataBands(in,
0332: methodAttrCalls);
0333:
0334: // Parse non-predefined attribute bands
0335: int backwardsCallIndex = backwardsCallsUsed;
0336: int limit = options.hasMethodFlagsHi() ? 62 : 31;
0337: AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
0338: int[] counts = new int[limit + 1];
0339: List[] otherAttributes = new List[limit + 1];
0340: for (int i = 0; i < limit; i++) {
0341: AttributeLayout layout = attrMap.getAttributeLayout(i,
0342: AttributeLayout.CONTEXT_METHOD);
0343: if (layout != null && !(layout.isDefaultLayout())) {
0344: otherLayouts[i] = layout;
0345: counts[i] = SegmentUtils.countMatches(methodFlags,
0346: layout);
0347: }
0348: }
0349: for (int i = 0; i < counts.length; i++) {
0350: if (counts[i] > 0) {
0351: NewAttributeBands bands = attrMap
0352: .getAttributeBands(otherLayouts[i]);
0353: otherAttributes[i] = bands.parseAttributes(in,
0354: counts[i]);
0355: int numBackwardsCallables = otherLayouts[i]
0356: .numBackwardsCallables();
0357: if (numBackwardsCallables > 0) {
0358: int[] backwardsCalls = new int[numBackwardsCallables];
0359: System.arraycopy(methodAttrCalls,
0360: backwardsCallIndex, backwardsCalls, 0,
0361: numBackwardsCallables);
0362: bands.setBackwardsCalls(backwardsCalls);
0363: backwardsCallIndex += numBackwardsCallables;
0364: }
0365: }
0366: }
0367:
0368: // Add attributes to the attribute arrays
0369: int methodExceptionsIndex = 0;
0370: int methodSignatureIndex = 0;
0371: for (int i = 0; i < methodAttributes.length; i++) {
0372: for (int j = 0; j < methodAttributes[i].length; j++) {
0373: long flag = methodFlags[i][j];
0374: if (methodExceptionsLayout.matches(flag)) {
0375: int n = numExceptions[methodExceptionsIndex];
0376: String[] exceptions = methodExceptionsRS[methodExceptionsIndex];
0377: CPClass[] exceptionClasses = new CPClass[n];
0378: for (int k = 0; k < n; k++) {
0379: exceptionClasses[k] = new CPClass(exceptions[k]);
0380: }
0381: methodAttributes[i][j].add(new ExceptionsAttribute(
0382: exceptionClasses));
0383: methodExceptionsIndex++;
0384: }
0385: if (methodSignatureLayout.matches(flag)) {
0386: // We've got a signature attribute
0387: long result = methodSignatureRS[methodSignatureIndex];
0388: String desc = methodDescr[i][j];
0389: int colon = desc.indexOf(':');
0390: String type = desc.substring(colon + 1);
0391: // TODO Got to get better at this ... in any case, it should
0392: // be e.g. KIB or KIH
0393: if (type.equals("B") || type.equals("H"))
0394: type = "I";
0395: Object value = methodSignatureLayout.getValue(
0396: result, type, cpBands.getConstantPool());
0397: methodAttributes[i][j]
0398: .add(new ConstantValueAttribute(value));
0399: methodSignatureIndex++;
0400: }
0401: // Non-predefined attributes
0402: for (int k = 0; k < otherLayouts.length; k++) {
0403: if (otherLayouts[k] != null
0404: && otherLayouts[k].matches(flag)) {
0405: // Add the next attribute
0406: methodAttributes[i][j].add(otherAttributes[k]
0407: .get(0));
0408: otherAttributes[k].remove(0);
0409: }
0410: }
0411: }
0412: }
0413: }
0414:
0415: private int getCallCount(int[][] methodAttrIndexes, long[][] flags,
0416: int context) throws Pack200Exception {
0417: int callCount = 0;
0418: for (int i = 0; i < methodAttrIndexes.length; i++) {
0419: for (int j = 0; j < methodAttrIndexes[i].length; j++) {
0420: int index = methodAttrIndexes[i][j];
0421: AttributeLayout layout = attrMap.getAttributeLayout(
0422: index, context);
0423: callCount += layout.numBackwardsCallables();
0424: }
0425: }
0426: int layoutsUsed = 0;
0427: for (int i = 0; i < flags.length; i++) {
0428: for (int j = 0; j < flags[i].length; j++) {
0429: layoutsUsed |= flags[i][j];
0430: }
0431: }
0432: for (int i = 0; i < 26; i++) {
0433: if ((layoutsUsed & 1 << i) != 0) {
0434: AttributeLayout layout = attrMap.getAttributeLayout(i,
0435: context);
0436: callCount += layout.numBackwardsCallables();
0437: }
0438: }
0439: return callCount;
0440: }
0441:
0442: private void parseClassAttrBands(InputStream in)
0443: throws IOException, Pack200Exception {
0444: String[] cpUTF8 = cpBands.getCpUTF8();
0445: String[] cpClass = cpBands.getCpClass();
0446:
0447: // Prepare empty attribute lists
0448: classAttributes = new ArrayList[classCount];
0449: for (int i = 0; i < classCount; i++) {
0450: classAttributes[i] = new ArrayList();
0451: }
0452:
0453: classFlags = parseFlags("class_flags", in, classCount,
0454: Codec.UNSIGNED5, options.hasClassFlagsHi());
0455: int classAttrCount = SegmentUtils.countBit16(classFlags);
0456: int[] classAttrCounts = decodeBandInt("class_attr_count", in,
0457: Codec.UNSIGNED5, classAttrCount);
0458: int[][] classAttrIndexes = decodeBandInt("class_attr_indexes",
0459: in, Codec.UNSIGNED5, classAttrCounts);
0460: int callCount = getCallCount(classAttrIndexes,
0461: new long[][] { classFlags },
0462: AttributeLayout.CONTEXT_CLASS);
0463: int[] classAttrCalls = decodeBandInt("class_attr_calls", in,
0464: Codec.UNSIGNED5, callCount);
0465:
0466: AttributeLayout sourceFileLayout = attrMap.getAttributeLayout(
0467: AttributeLayout.ATTRIBUTE_SOURCE_FILE,
0468: AttributeLayout.CONTEXT_CLASS);
0469: int sourceFileCount = SegmentUtils.countMatches(classFlags,
0470: sourceFileLayout);
0471: int[] classSourceFile = decodeBandInt("class_SourceFile_RUN",
0472: in, Codec.UNSIGNED5, sourceFileCount);
0473:
0474: AttributeLayout enclosingMethodLayout = attrMap
0475: .getAttributeLayout(
0476: AttributeLayout.ATTRIBUTE_ENCLOSING_METHOD,
0477: AttributeLayout.CONTEXT_CLASS);
0478: int enclosingMethodCount = SegmentUtils.countMatches(
0479: classFlags, enclosingMethodLayout);
0480: String[] enclosingMethodRC = parseReferences(
0481: "class_EnclosingMethod_RC", in, Codec.UNSIGNED5,
0482: enclosingMethodCount, cpClass);
0483: String[] enclosingMethodRDN = parseReferences(
0484: "class_EnclosingMethod_RDN", in, Codec.UNSIGNED5,
0485: enclosingMethodCount, cpBands.getCpDescriptor());
0486:
0487: AttributeLayout signatureLayout = attrMap.getAttributeLayout(
0488: AttributeLayout.ATTRIBUTE_SIGNATURE,
0489: AttributeLayout.CONTEXT_CLASS);
0490: int signatureCount = SegmentUtils.countMatches(classFlags,
0491: signatureLayout);
0492: int[] classSignature = decodeBandInt("class_Signature_RS", in,
0493: Codec.UNSIGNED5, signatureCount);
0494:
0495: int backwardsCallsUsed = parseClassMetadataBands(in,
0496: classAttrCalls);
0497:
0498: AttributeLayout innerClassLayout = attrMap.getAttributeLayout(
0499: AttributeLayout.ATTRIBUTE_INNER_CLASSES,
0500: AttributeLayout.CONTEXT_CLASS);
0501: int innerClassCount = SegmentUtils.countMatches(classFlags,
0502: innerClassLayout);
0503: int[] classInnerClassesN = decodeBandInt(
0504: "class_InnerClasses_N", in, Codec.UNSIGNED5,
0505: innerClassCount);
0506: int[][] classInnerClassesRC = decodeBandInt(
0507: "class_InnerClasses_RC", in, Codec.UNSIGNED5,
0508: classInnerClassesN);
0509: int[][] classInnerClassesF = decodeBandInt(
0510: "class_InnerClasses_F", in, Codec.UNSIGNED5,
0511: classInnerClassesN);
0512: int flagsCount = 0;
0513: for (int i = 0; i < classInnerClassesF.length; i++) {
0514: for (int j = 0; j < classInnerClassesF[i].length; j++) {
0515: if (classInnerClassesF[i][j] != 0) {
0516: flagsCount++;
0517: }
0518: }
0519: }
0520: int[] classInnerClassesOuterRCN = decodeBandInt(
0521: "class_InnerClasses_outer_RCN", in, Codec.UNSIGNED5,
0522: flagsCount);
0523: int[] classInnerClassesNameRUN = decodeBandInt(
0524: "class_InnerClasses_name_RUN", in, Codec.UNSIGNED5,
0525: flagsCount);
0526:
0527: AttributeLayout versionLayout = attrMap.getAttributeLayout(
0528: AttributeLayout.ATTRIBUTE_CLASS_FILE_VERSION,
0529: AttributeLayout.CONTEXT_CLASS);
0530: int versionCount = SegmentUtils.countMatches(classFlags,
0531: versionLayout);
0532: int[] classFileVersionMinorH = decodeBandInt(
0533: "class_file_version_minor_H", in, Codec.UNSIGNED5,
0534: versionCount);
0535: int[] classFileVersionMajorH = decodeBandInt(
0536: "class_file_version_major_H", in, Codec.UNSIGNED5,
0537: versionCount);
0538: if (versionCount > 0) {
0539: classVersionMajor = new int[classCount];
0540: classVersionMinor = new int[classCount];
0541: }
0542: int defaultVersionMajor = header.getDefaultClassMajorVersion();
0543: int defaultVersionMinor = header.getDefaultClassMinorVersion();
0544:
0545: // Parse non-predefined attribute bands
0546: int backwardsCallIndex = backwardsCallsUsed;
0547: int limit = options.hasClassFlagsHi() ? 62 : 31;
0548: AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
0549: int[] counts = new int[limit + 1];
0550: List[] otherAttributes = new List[limit + 1];
0551: for (int i = 0; i < limit; i++) {
0552: AttributeLayout layout = attrMap.getAttributeLayout(i,
0553: AttributeLayout.CONTEXT_CLASS);
0554: if (layout != null && !(layout.isDefaultLayout())) {
0555: otherLayouts[i] = layout;
0556: counts[i] = SegmentUtils.countMatches(classFlags,
0557: layout);
0558: }
0559: }
0560: for (int i = 0; i < counts.length; i++) {
0561: if (counts[i] > 0) {
0562: NewAttributeBands bands = attrMap
0563: .getAttributeBands(otherLayouts[i]);
0564: otherAttributes[i] = bands.parseAttributes(in,
0565: counts[i]);
0566: int numBackwardsCallables = otherLayouts[i]
0567: .numBackwardsCallables();
0568: if (numBackwardsCallables > 0) {
0569: int[] backwardsCalls = new int[numBackwardsCallables];
0570: System.arraycopy(classAttrCalls,
0571: backwardsCallIndex, backwardsCalls, 0,
0572: numBackwardsCallables);
0573: bands.setBackwardsCalls(backwardsCalls);
0574: backwardsCallIndex += numBackwardsCallables;
0575: }
0576: }
0577: }
0578:
0579: // Now process the attribute bands we have parsed
0580: int sourceFileIndex = 0;
0581: int enclosingMethodIndex = 0;
0582: int signatureIndex = 0;
0583: int innerClassIndex = 0;
0584: int innerClassC2NIndex = 0;
0585: int versionIndex = 0;
0586: icLocal = new IcTuple[classCount][];
0587: for (int i = 0; i < classCount; i++) {
0588: long flag = classFlags[i];
0589:
0590: if (sourceFileLayout.matches(flag)) {
0591: long result = classSourceFile[sourceFileIndex];
0592: String value = (String) sourceFileLayout.getValue(
0593: result, cpBands.getConstantPool());
0594: if (value == null) {
0595: // Remove package prefix
0596: String className = classThis[i]
0597: .substring(classThis[i].lastIndexOf('/') + 1);
0598: className = className.substring(className
0599: .lastIndexOf('.') + 1);
0600:
0601: // Remove mangled nested class names
0602: char[] chars = className.toCharArray();
0603: int index = -1;
0604: for (int j = 0; j < chars.length; j++) {
0605: if (chars[j] <= 0x2D) {
0606: index = j;
0607: break;
0608: }
0609: }
0610: if (index > -1) {
0611: className = className.substring(0, index);
0612: }
0613: // Add .java to the end
0614: value = className + ".java";
0615: }
0616: classAttributes[i].add(new SourceFileAttribute(value));
0617: sourceFileIndex++;
0618: }
0619: if (enclosingMethodLayout.matches(flag)) {
0620: CPClass theClass = new CPClass(
0621: enclosingMethodRC[enclosingMethodIndex]);
0622: CPNameAndType theMethod = new CPNameAndType(
0623: enclosingMethodRDN[enclosingMethodIndex]);
0624: classAttributes[i].add(new EnclosingMethodAttribute(
0625: theClass, theMethod));
0626: enclosingMethodIndex++;
0627: }
0628: if (signatureLayout.matches(flag)) {
0629: long result = classSignature[signatureIndex];
0630: Object value = signatureLayout.getValue(result, cpBands
0631: .getConstantPool());
0632: classAttributes[i]
0633: .add(new ConstantValueAttribute(value));
0634: signatureIndex++;
0635: }
0636: if (innerClassLayout.matches(flag)) {
0637: // Just create the tuples for now because the attributes are
0638: // decided at the end when creating class constant pools
0639: icLocal[i] = new IcTuple[classInnerClassesN[innerClassIndex]];
0640: for (int j = 0; j < icLocal[i].length; j++) {
0641: IcTuple icTuple = new IcTuple();
0642: icTuple.C = cpClass[classInnerClassesRC[innerClassIndex][j]];
0643: icTuple.F = classInnerClassesF[innerClassIndex][j];
0644: if (icTuple.F != 0) {
0645: icTuple.C2 = cpClass[classInnerClassesOuterRCN[innerClassC2NIndex]];
0646: icTuple.N = cpUTF8[classInnerClassesNameRUN[innerClassC2NIndex]];
0647: innerClassC2NIndex++;
0648: } else {
0649: // Get from icBands
0650: IcBands icBands = segment.getIcBands();
0651: IcTuple[] icAll = icBands.getIcTuples();
0652: for (int k = 0; k < icAll.length; k++) {
0653: if (icAll[k].C.equals(icTuple.C)) {
0654: icTuple.C2 = icAll[k].C2;
0655: icTuple.N = icAll[k].N;
0656: break;
0657: }
0658: }
0659: }
0660: icLocal[i][j] = icTuple;
0661: }
0662: innerClassIndex++;
0663: }
0664: if (versionLayout.matches(flag)) {
0665: classVersionMajor[i] = classFileVersionMajorH[versionIndex];
0666: classVersionMinor[i] = classFileVersionMinorH[versionIndex];
0667: versionIndex++;
0668: } else if (classVersionMajor != null) {
0669: // Fill in with defaults
0670: classVersionMajor[i] = defaultVersionMajor;
0671: classVersionMinor[i] = defaultVersionMinor;
0672: }
0673: // Non-predefined attributes
0674: for (int j = 0; j < otherLayouts.length; j++) {
0675: if (otherLayouts[j] != null
0676: && otherLayouts[j].matches(flag)) {
0677: // Add the next attribute
0678: classAttributes[i].add(otherAttributes[j].get(0));
0679: otherAttributes[j].remove(0);
0680: }
0681: }
0682: }
0683: }
0684:
0685: private void parseCodeBands(InputStream in)
0686: throws Pack200Exception, IOException {
0687: AttributeLayout layout = attrMap.getAttributeLayout(
0688: AttributeLayout.ATTRIBUTE_CODE,
0689: AttributeLayout.CONTEXT_METHOD);
0690:
0691: int codeCount = SegmentUtils.countMatches(methodFlags, layout);
0692: int[] codeHeaders = decodeBandInt("code_headers", in,
0693: Codec.BYTE1, codeCount);
0694: int codeSpecialHeader = 0;
0695: for (int i = 0; i < codeCount; i++) {
0696: if (codeHeaders[i] == 0)
0697: codeSpecialHeader++;
0698: }
0699: int[] codeMaxStackSpecials = decodeBandInt("code_max_stack",
0700: in, Codec.UNSIGNED5, codeSpecialHeader);
0701: int[] codeMaxNALocalsSpecials = decodeBandInt(
0702: "code_max_na_locals", in, Codec.UNSIGNED5,
0703: codeSpecialHeader);
0704: int[] codeHandlerCountSpecials = decodeBandInt(
0705: "code_handler_count", in, Codec.UNSIGNED5,
0706: codeSpecialHeader);
0707:
0708: codeMaxStack = new int[codeCount];
0709: codeMaxNALocals = new int[codeCount];
0710: codeHandlerCount = new int[codeCount];
0711: int special = 0;
0712: for (int i = 0; i < codeCount; i++) {
0713: int header = 0xff & codeHeaders[i];
0714: if (header < 0) {
0715: throw new IllegalStateException("Shouldn't get here");
0716: } else if (header == 0) {
0717: codeMaxStack[i] = codeMaxStackSpecials[special];
0718: codeMaxNALocals[i] = codeMaxNALocalsSpecials[special];
0719: codeHandlerCount[i] = codeHandlerCountSpecials[special];
0720: special++;
0721: } else if (header <= 144) {
0722: codeMaxStack[i] = (header - 1) % 12;
0723: codeMaxNALocals[i] = (header - 1) / 12;
0724: codeHandlerCount[i] = 0;
0725: } else if (header <= 208) {
0726: codeMaxStack[i] = (header - 145) % 8;
0727: codeMaxNALocals[i] = (header - 145) / 8;
0728: codeHandlerCount[i] = 1;
0729: } else if (header <= 255) {
0730: codeMaxStack[i] = (header - 209) % 7;
0731: codeMaxNALocals[i] = (header - 209) / 7;
0732: codeHandlerCount[i] = 2;
0733: } else {
0734: throw new IllegalStateException(
0735: "Shouldn't get here either");
0736: }
0737: }
0738: codeHandlerStartP = decodeBandInt("code_handler_start_P", in,
0739: Codec.BCI5, codeHandlerCount);
0740: codeHandlerEndPO = decodeBandInt("code_handler_end_PO", in,
0741: Codec.BRANCH5, codeHandlerCount);
0742: codeHandlerCatchPO = decodeBandInt("code_handler_catch_PO", in,
0743: Codec.BRANCH5, codeHandlerCount);
0744: int[][] codeHandlerClassRCNints = decodeBandInt(
0745: "code_handler_class_RCN", in, Codec.UNSIGNED5,
0746: codeHandlerCount);
0747: // The codeHandlerClassRCN band contains incremented references to
0748: // cp_Class so we can't use parseReferences(..) here.
0749: String[] cpClass = cpBands.getCpClass();
0750: codeHandlerClassRCN = new String[codeHandlerClassRCNints.length][];
0751: for (int i = 0; i < codeHandlerClassRCNints.length; i++) {
0752: codeHandlerClassRCN[i] = new String[codeHandlerClassRCNints[i].length];
0753: for (int j = 0; j < codeHandlerClassRCNints[i].length; j++) {
0754: int handlerClassReference = codeHandlerClassRCNints[i][j];
0755: if (handlerClassReference == 0) {
0756: codeHandlerClassRCN[i][j] = null;
0757: } else {
0758: codeHandlerClassRCN[i][j] = cpClass[handlerClassReference - 1];
0759: }
0760: }
0761: }
0762:
0763: int codeFlagsCount = segment.getSegmentHeader().getOptions()
0764: .hasAllCodeFlags() ? codeCount : codeSpecialHeader;
0765:
0766: codeAttributes = new ArrayList[codeFlagsCount];
0767: for (int i = 0; i < codeAttributes.length; i++) {
0768: codeAttributes[i] = new ArrayList();
0769: }
0770: parseCodeAttrBands(in, codeFlagsCount);
0771: }
0772:
0773: private void parseCodeAttrBands(InputStream in, int codeFlagsCount)
0774: throws IOException, Pack200Exception {
0775: long[] codeFlags = parseFlags("code_flags", in, codeFlagsCount,
0776: Codec.UNSIGNED5, segment.getSegmentHeader()
0777: .getOptions().hasCodeFlagsHi());
0778: int codeAttrCount = SegmentUtils.countBit16(codeFlags);
0779: int[] codeAttrCounts = decodeBandInt("code_attr_count", in,
0780: Codec.UNSIGNED5, codeAttrCount);
0781: int[][] codeAttrIndexes = decodeBandInt("code_attr_indexes",
0782: in, Codec.UNSIGNED5, codeAttrCounts);
0783: int callCount = 0;
0784: for (int i = 0; i < codeAttrIndexes.length; i++) {
0785: for (int j = 0; j < codeAttrIndexes[i].length; j++) {
0786: int index = codeAttrIndexes[i][j];
0787: AttributeLayout layout = attrMap.getAttributeLayout(
0788: index, AttributeLayout.CONTEXT_CODE);
0789: callCount += layout.numBackwardsCallables();
0790: }
0791: }
0792: int[] codeAttrCalls = decodeBandInt("code_attr_calls", in,
0793: Codec.UNSIGNED5, callCount);
0794:
0795: AttributeLayout lineNumberTableLayout = attrMap
0796: .getAttributeLayout(
0797: AttributeLayout.ATTRIBUTE_LINE_NUMBER_TABLE,
0798: AttributeLayout.CONTEXT_CODE);
0799: int lineNumberTableCount = SegmentUtils.countMatches(codeFlags,
0800: lineNumberTableLayout);
0801: int[] lineNumberTableN = decodeBandInt(
0802: "code_LineNumberTable_N", in, Codec.UNSIGNED5,
0803: lineNumberTableCount);
0804: int[][] lineNumberTableBciP = decodeBandInt(
0805: "code_LineNumberTable_bci_P", in, Codec.BCI5,
0806: lineNumberTableN);
0807: int[][] lineNumberTableLine = decodeBandInt(
0808: "code_LineNumberTable_line", in, Codec.UNSIGNED5,
0809: lineNumberTableN);
0810:
0811: AttributeLayout localVariableTableLayout = attrMap
0812: .getAttributeLayout(
0813: AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TABLE,
0814: AttributeLayout.CONTEXT_CODE);
0815: AttributeLayout localVariableTypeTableLayout = attrMap
0816: .getAttributeLayout(
0817: AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE,
0818: AttributeLayout.CONTEXT_CODE);
0819:
0820: int lengthLocalVariableNBand = SegmentUtils.countMatches(
0821: codeFlags, localVariableTableLayout);
0822: int[] localVariableTableN = decodeBandInt(
0823: "code_LocalVariableTable_N", in, Codec.UNSIGNED5,
0824: lengthLocalVariableNBand);
0825: int[][] localVariableTableBciP = decodeBandInt(
0826: "code_LocalVariableTable_bci_P", in, Codec.BCI5,
0827: localVariableTableN);
0828: int[][] localVariableTableSpanO = decodeBandInt(
0829: "code_LocalVariableTable_span_O", in, Codec.BRANCH5,
0830: localVariableTableN);
0831: CPUTF8[][] localVariableTableNameRU = stringsToCPUTF8(parseReferences(
0832: "code_LocalVariableTable_name_RU", in, Codec.UNSIGNED5,
0833: localVariableTableN, cpBands.getCpUTF8()));
0834: CPUTF8[][] localVariableTableTypeRS = stringsToCPUTF8(parseReferences(
0835: "code_LocalVariableTable_type_RS", in, Codec.UNSIGNED5,
0836: localVariableTableN, cpBands.getCpSignature()));
0837: int[][] localVariableTableSlot = decodeBandInt(
0838: "code_LocalVariableTable_slot", in, Codec.UNSIGNED5,
0839: localVariableTableN);
0840:
0841: // Fix up localVariableTableTypeRS - for some reason,
0842: // native signatures end up in DOMAINNORMALASCIIZ
0843: // while nonnatives end up in DOMAINSIGNATUREASCIIZ.
0844: // TODO: is this the right thing to do?
0845: for (int x = 0; x < localVariableTableTypeRS.length; x++) {
0846: for (int y = 0; y < localVariableTableTypeRS[x].length; y++) {
0847: CPUTF8 element = localVariableTableTypeRS[x][y];
0848: // TODO: come up with a better test for native vs nonnative signatures?
0849: if (element.underlyingString().length() > 2) {
0850: element
0851: .setDomain(ClassConstantPool.DOMAIN_SIGNATUREASCIIZ);
0852: } else {
0853: element
0854: .setDomain(ClassConstantPool.DOMAIN_NORMALASCIIZ);
0855: }
0856: }
0857: }
0858:
0859: int lengthLocalVariableTypeTableNBand = SegmentUtils
0860: .countMatches(codeFlags, localVariableTypeTableLayout);
0861: int[] localVariableTypeTableN = decodeBandInt(
0862: "code_LocalVariableTypeTable_N", in, Codec.UNSIGNED5,
0863: lengthLocalVariableTypeTableNBand);
0864: int[][] localVariableTypeTableBciP = decodeBandInt(
0865: "code_LocalVariableTypeTable_bci_P", in, Codec.BCI5,
0866: localVariableTypeTableN);
0867: int[][] localVariableTypeTableSpanO = decodeBandInt(
0868: "code_LocalVariableTypeTable_span_O", in,
0869: Codec.BRANCH5, localVariableTypeTableN);
0870: CPUTF8[][] localVariableTypeTableNameRU = stringsToCPUTF8(parseReferences(
0871: "code_LocalVariableTypeTable_name_RU", in,
0872: Codec.UNSIGNED5, localVariableTypeTableN, cpBands
0873: .getCpUTF8()));
0874: CPUTF8[][] localVariableTypeTableTypeRS = stringsToCPUTF8(parseReferences(
0875: "code_LocalVariableTypeTable_type_RS", in,
0876: Codec.UNSIGNED5, localVariableTypeTableN, cpBands
0877: .getCpSignature()));
0878: int[][] localVariableTypeTableSlot = decodeBandInt(
0879: "code_LocalVariableTypeTable_slot", in,
0880: Codec.UNSIGNED5, localVariableTypeTableN);
0881:
0882: // Parse non-predefined attribute bands
0883: int backwardsCallIndex = 0;
0884: int limit = options.hasCodeFlagsHi() ? 62 : 31;
0885: AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
0886: int[] counts = new int[limit + 1];
0887: List[] otherAttributes = new List[limit + 1];
0888: for (int i = 0; i < limit; i++) {
0889: AttributeLayout layout = attrMap.getAttributeLayout(i,
0890: AttributeLayout.CONTEXT_CODE);
0891: if (layout != null && !(layout.isDefaultLayout())) {
0892: otherLayouts[i] = layout;
0893: counts[i] = SegmentUtils
0894: .countMatches(codeFlags, layout);
0895: }
0896: }
0897: for (int i = 0; i < counts.length; i++) {
0898: if (counts[i] > 0) {
0899: NewAttributeBands bands = attrMap
0900: .getAttributeBands(otherLayouts[i]);
0901: otherAttributes[i] = bands.parseAttributes(in,
0902: counts[i]);
0903: int numBackwardsCallables = otherLayouts[i]
0904: .numBackwardsCallables();
0905: if (numBackwardsCallables > 0) {
0906: int[] backwardsCalls = new int[numBackwardsCallables];
0907: System.arraycopy(codeAttrCalls, backwardsCallIndex,
0908: backwardsCalls, 0, numBackwardsCallables);
0909: bands.setBackwardsCalls(backwardsCalls);
0910: backwardsCallIndex += numBackwardsCallables;
0911: }
0912: }
0913: }
0914:
0915: int lineNumberIndex = 0;
0916: int lvtIndex = 0;
0917: int lvttIndex = 0;
0918: for (int i = 0; i < codeFlagsCount; i++) {
0919: if (lineNumberTableLayout.matches(codeFlags[i])) {
0920: LineNumberTableAttribute lnta = new LineNumberTableAttribute(
0921: lineNumberTableN[lineNumberIndex],
0922: lineNumberTableBciP[lineNumberIndex],
0923: lineNumberTableLine[lineNumberIndex]);
0924: lineNumberIndex++;
0925: codeAttributes[i].add(lnta);
0926: }
0927: if (localVariableTableLayout.matches(codeFlags[i])) {
0928: LocalVariableTableAttribute lvta = new LocalVariableTableAttribute(
0929: localVariableTableN[lvtIndex],
0930: localVariableTableBciP[lvtIndex],
0931: localVariableTableSpanO[lvtIndex],
0932: localVariableTableNameRU[lvtIndex],
0933: localVariableTableTypeRS[lvtIndex],
0934: localVariableTableSlot[lvtIndex]);
0935: lvtIndex++;
0936: codeAttributes[i].add(lvta);
0937: }
0938: if (localVariableTypeTableLayout.matches(codeFlags[i])) {
0939: LocalVariableTypeTableAttribute lvtta = new LocalVariableTypeTableAttribute(
0940: localVariableTypeTableN[lvttIndex],
0941: localVariableTypeTableBciP[lvttIndex],
0942: localVariableTypeTableSpanO[lvttIndex],
0943: localVariableTypeTableNameRU[lvttIndex],
0944: localVariableTypeTableTypeRS[lvttIndex],
0945: localVariableTypeTableSlot[lvttIndex]);
0946: lvttIndex++;
0947: codeAttributes[i].add(lvtta);
0948: }
0949: // Non-predefined attributes
0950: for (int j = 0; j < otherLayouts.length; j++) {
0951: if (otherLayouts[j] != null
0952: && otherLayouts[j].matches(codeFlags[i])) {
0953: // Add the next attribute
0954: codeAttributes[i].add(otherAttributes[j].get(0));
0955: otherAttributes[j].remove(0);
0956: }
0957: }
0958: }
0959:
0960: }
0961:
0962: private CPUTF8[][] stringsToCPUTF8(String[][] strings) {
0963: CPUTF8[][] cpUTF8s = new CPUTF8[strings.length][];
0964: for (int i = 0; i < strings.length; i++) {
0965: cpUTF8s[i] = new CPUTF8[strings[i].length];
0966: for (int j = 0; j < strings[i].length; j++) {
0967: cpUTF8s[i][j] = new CPUTF8(strings[i][j],
0968: ClassConstantPool.DOMAIN_NORMALASCIIZ);
0969: }
0970: }
0971: return cpUTF8s;
0972: }
0973:
0974: private CPUTF8[] stringsToCPUTF8(String[] strings) {
0975: CPUTF8[] cpUTF8s = new CPUTF8[strings.length];
0976: for (int i = 0; i < strings.length; i++) {
0977: cpUTF8s[i] = new CPUTF8(strings[i],
0978: ClassConstantPool.DOMAIN_UNDEFINED);
0979: }
0980: return cpUTF8s;
0981: }
0982:
0983: private int parseFieldMetadataBands(InputStream in,
0984: int[] fieldAttrCalls) throws Pack200Exception, IOException {
0985: int backwardsCallsUsed = 0;
0986: String[] RxA = new String[] { "RVA", "RIA" };
0987:
0988: AttributeLayout rvaLayout = attrMap.getAttributeLayout(
0989: AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS,
0990: AttributeLayout.CONTEXT_FIELD);
0991: AttributeLayout riaLayout = attrMap
0992: .getAttributeLayout(
0993: AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS,
0994: AttributeLayout.CONTEXT_FIELD);
0995:
0996: int rvaCount = SegmentUtils.countMatches(fieldFlags, rvaLayout);
0997: int riaCount = SegmentUtils.countMatches(fieldFlags, riaLayout);
0998: int[] RxACount = new int[] { rvaCount, riaCount };
0999: int[] backwardsCalls = new int[] { 0, 0 };
1000: if (rvaCount > 0) {
1001: backwardsCalls[0] = fieldAttrCalls[0];
1002: backwardsCallsUsed++;
1003: if (riaCount > 0) {
1004: backwardsCalls[1] = fieldAttrCalls[1];
1005: backwardsCallsUsed++;
1006: }
1007: } else if (riaCount > 0) {
1008: backwardsCalls[1] = fieldAttrCalls[0];
1009: backwardsCallsUsed++;
1010: }
1011: MetadataBandGroup[] mb = parseMetadata(in, RxA, RxACount,
1012: backwardsCalls, "field");
1013: Iterator rvaAttributesIterator = mb[0].getAttributes()
1014: .iterator();
1015: Iterator riaAttributesIterator = mb[1].getAttributes()
1016: .iterator();
1017: for (int i = 0; i < fieldFlags.length; i++) {
1018: for (int j = 0; j < fieldFlags[i].length; j++) {
1019: if (rvaLayout.matches(fieldFlags[i][j])) {
1020: fieldAttributes[i][j].add(rvaAttributesIterator
1021: .next());
1022: }
1023: if (riaLayout.matches(fieldFlags[i][j])) {
1024: fieldAttributes[i][j].add(riaAttributesIterator
1025: .next());
1026: }
1027: }
1028: }
1029: return backwardsCallsUsed;
1030: }
1031:
1032: private MetadataBandGroup[] parseMetadata(InputStream in,
1033: String[] RxA, int[] RxACount, int[] backwardsCallCounts,
1034: String contextName) throws IOException, Pack200Exception {
1035: MetadataBandGroup[] mbg = new MetadataBandGroup[RxA.length];
1036: for (int i = 0; i < RxA.length; i++) {
1037: mbg[i] = new MetadataBandGroup(RxA[i]);
1038: String rxa = RxA[i];
1039: if (rxa.indexOf("P") >= 0) {
1040: mbg[i].param_NB = decodeBandInt(contextName + "_" + rxa
1041: + "_param_NB", in, Codec.BYTE1, RxACount[i]);
1042: }
1043: int pairCount = 0;
1044: if (!rxa.equals("AD")) {
1045: mbg[i].anno_N = decodeBandInt(contextName + "_" + rxa
1046: + "_anno_N", in, Codec.UNSIGNED5, RxACount[i]);
1047: mbg[i].type_RS = stringsToCPUTF8(parseReferences(
1048: contextName + "_" + rxa + "_type_RS", in,
1049: Codec.UNSIGNED5, mbg[i].anno_N, cpBands
1050: .getCpSignature()));
1051: mbg[i].pair_N = decodeBandInt(contextName + "_" + rxa
1052: + "_pair_N", in, Codec.UNSIGNED5, mbg[i].anno_N);
1053: for (int j = 0; j < mbg[i].pair_N.length; j++) {
1054: for (int k = 0; k < mbg[i].pair_N[j].length; k++) {
1055: pairCount += mbg[i].pair_N[j][k];
1056: }
1057: }
1058:
1059: mbg[i].name_RU = stringsToCPUTF8(parseReferences(
1060: contextName + "_" + rxa + "_name_RU", in,
1061: Codec.UNSIGNED5, pairCount, cpBands.getCpUTF8()));
1062: }
1063: mbg[i].T = decodeBandInt(contextName + "_" + rxa + "_T",
1064: in, Codec.BYTE1, pairCount + backwardsCallCounts[i]);
1065: int ICount = 0, DCount = 0, FCount = 0, JCount = 0, cCount = 0, eCount = 0, sCount = 0, arrayCount = 0, atCount = 0;
1066: for (int j = 0; j < mbg[i].T.length; j++) {
1067: char c = (char) mbg[i].T[j];
1068: switch (c) {
1069: case 'B':
1070: case 'C':
1071: case 'I':
1072: case 'S':
1073: case 'Z':
1074: ICount++;
1075: break;
1076: case 'D':
1077: DCount++;
1078: break;
1079: case 'F':
1080: FCount++;
1081: break;
1082: case 'J':
1083: JCount++;
1084: break;
1085: case 'c':
1086: cCount++;
1087: break;
1088: case 'e':
1089: eCount++;
1090: break;
1091: case 's':
1092: sCount++;
1093: break;
1094: case '[':
1095: arrayCount++;
1096: break;
1097: case '@':
1098: atCount++;
1099: break;
1100: }
1101: }
1102: mbg[i].caseI_KI = parseCPIntReferences(contextName + "_"
1103: + rxa + "_caseI_KI", in, Codec.UNSIGNED5, ICount);
1104: mbg[i].caseD_KD = parseCPDoubleReferences(contextName + "_"
1105: + rxa + "_caseD_KD", in, Codec.UNSIGNED5, DCount);
1106: mbg[i].caseF_KF = parseCPFloatReferences(contextName + "_"
1107: + rxa + "_caseF_KF", in, Codec.UNSIGNED5, FCount);
1108: mbg[i].caseJ_KJ = parseCPLongReferences(contextName + "_"
1109: + rxa + "_caseJ_KJ", in, Codec.UNSIGNED5, JCount);
1110: mbg[i].casec_RS = parseCPUTF8References(contextName + "_"
1111: + rxa + "_casec_RS", in, Codec.UNSIGNED5, cCount);
1112: mbg[i].caseet_RS = parseReferences(contextName + "_" + rxa
1113: + "_caseet_RS", in, Codec.UNSIGNED5, eCount,
1114: cpBands.getCpSignature());
1115: mbg[i].caseec_RU = parseReferences(contextName + "_" + rxa
1116: + "_caseec_RU", in, Codec.UNSIGNED5, eCount,
1117: cpBands.getCpUTF8());
1118: mbg[i].cases_RU = parseCPUTF8References(contextName + "_"
1119: + rxa + "_cases_RU", in, Codec.UNSIGNED5, sCount);
1120: mbg[i].casearray_N = decodeBandInt(contextName + "_" + rxa
1121: + "_casearray_N", in, Codec.UNSIGNED5, arrayCount);
1122: mbg[i].nesttype_RS = parseCPUTF8References(contextName
1123: + "_" + rxa + "_nesttype_RS", in, Codec.UNSIGNED5,
1124: atCount);
1125: mbg[i].nestpair_N = decodeBandInt(contextName + "_" + rxa
1126: + "_nestpair_N", in, Codec.UNSIGNED5, atCount);
1127: int nestPairCount = 0;
1128: for (int j = 0; j < mbg[i].nestpair_N.length; j++) {
1129: nestPairCount += mbg[i].nestpair_N[j];
1130: }
1131: mbg[i].nestname_RU = parseCPUTF8References(contextName
1132: + "_" + rxa + "_nestname_RU", in, Codec.UNSIGNED5,
1133: nestPairCount);
1134: }
1135: return mbg;
1136: }
1137:
1138: private int parseMethodMetadataBands(InputStream in,
1139: int[] methodAttrCalls) throws Pack200Exception, IOException {
1140: int backwardsCallsUsed = 0;
1141: String[] RxA = new String[] { "RVA", "RIA", "RVPA", "RIPA",
1142: "AD" };
1143: int[] rxaCounts = new int[] { 0, 0, 0, 0, 0 };
1144: int[] backwardsCalls = new int[5];
1145: int methodAttrIndex = 0;
1146: for (int i = 0; i < backwardsCalls.length; i++) {
1147: if (rxaCounts[i] > 0) {
1148: backwardsCallsUsed++;
1149: backwardsCalls[i] = methodAttrCalls[methodAttrIndex];
1150: methodAttrIndex++;
1151: } else {
1152: backwardsCalls[i] = 0;
1153: }
1154: }
1155: AttributeLayout rvaLayout = attrMap.getAttributeLayout(
1156: AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS,
1157: AttributeLayout.CONTEXT_METHOD);
1158: AttributeLayout riaLayout = attrMap
1159: .getAttributeLayout(
1160: AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS,
1161: AttributeLayout.CONTEXT_METHOD);
1162: AttributeLayout rvpaLayout = attrMap
1163: .getAttributeLayout(
1164: AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS,
1165: AttributeLayout.CONTEXT_METHOD);
1166: AttributeLayout ripaLayout = attrMap
1167: .getAttributeLayout(
1168: AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS,
1169: AttributeLayout.CONTEXT_METHOD);
1170: AttributeLayout adLayout = attrMap.getAttributeLayout(
1171: AttributeLayout.ATTRIBUTE_ANNOTATION_DEFAULT,
1172: AttributeLayout.CONTEXT_METHOD);
1173: AttributeLayout[] rxaLayouts = new AttributeLayout[] {
1174: rvaLayout, riaLayout, rvpaLayout, ripaLayout, adLayout };
1175:
1176: for (int i = 0; i < rxaLayouts.length; i++) {
1177: rxaCounts[i] = SegmentUtils.countMatches(methodFlags,
1178: rxaLayouts[i]);
1179: }
1180: MetadataBandGroup[] mbgs = parseMetadata(in, RxA, rxaCounts,
1181: backwardsCalls, "method");
1182: Iterator[] attributeIterators = new Iterator[RxA.length];
1183: for (int i = 0; i < mbgs.length; i++) {
1184: attributeIterators[i] = mbgs[i].getAttributes().iterator();
1185: }
1186: for (int i = 0; i < methodFlags.length; i++) {
1187: for (int j = 0; j < methodFlags[i].length; j++) {
1188: for (int k = 0; k < rxaLayouts.length; k++) {
1189: if (rxaLayouts[k].matches(methodFlags[i][j])) {
1190: methodAttributes[i][j]
1191: .add(attributeIterators[k].next());
1192: }
1193: }
1194: }
1195: }
1196: return backwardsCallsUsed;
1197: }
1198:
1199: /**
1200: * Parse the class metadata bands and return the number of backwards callables
1201: * @param in
1202: * @param classAttrCalls
1203: * @return
1204: * @throws Pack200Exception
1205: * @throws IOException
1206: */
1207: private int parseClassMetadataBands(InputStream in,
1208: int[] classAttrCalls) throws Pack200Exception, IOException {
1209: int numBackwardsCalls = 0;
1210: String[] RxA = new String[] { "RVA", "RIA" };
1211:
1212: AttributeLayout rvaLayout = attrMap.getAttributeLayout(
1213: AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS,
1214: AttributeLayout.CONTEXT_CLASS);
1215: AttributeLayout riaLayout = attrMap
1216: .getAttributeLayout(
1217: AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS,
1218: AttributeLayout.CONTEXT_CLASS);
1219: int rvaCount = SegmentUtils.countMatches(classFlags, rvaLayout);
1220: int riaCount = SegmentUtils.countMatches(classFlags, riaLayout);
1221: int[] RxACount = new int[] { rvaCount, riaCount };
1222: int[] backwardsCalls = new int[] { 0, 0 };
1223: if (rvaCount > 0) {
1224: numBackwardsCalls++;
1225: backwardsCalls[0] = classAttrCalls[0];
1226: if (riaCount > 0) {
1227: numBackwardsCalls++;
1228: backwardsCalls[1] = classAttrCalls[1];
1229: }
1230: } else if (riaCount > 0) {
1231: numBackwardsCalls++;
1232: backwardsCalls[1] = classAttrCalls[0];
1233: }
1234: MetadataBandGroup[] mbgs = parseMetadata(in, RxA, RxACount,
1235: backwardsCalls, "class");
1236: Iterator rvaAttributesIterator = mbgs[0].getAttributes()
1237: .iterator();
1238: Iterator riaAttributesIterator = mbgs[1].getAttributes()
1239: .iterator();
1240: for (int i = 0; i < classFlags.length; i++) {
1241: if (rvaLayout.matches(classFlags[i])) {
1242: classAttributes[i].add(rvaAttributesIterator.next());
1243: }
1244: if (riaLayout.matches(classFlags[i])) {
1245: classAttributes[i].add(riaAttributesIterator.next());
1246: }
1247: }
1248: return numBackwardsCalls;
1249: }
1250:
1251: public int[] getClassFieldCount() {
1252: return classFieldCount;
1253: }
1254:
1255: public long[] getClassFlags() {
1256: return classFlags;
1257: }
1258:
1259: public String[][] getClassInterfaces() {
1260: return classInterfaces;
1261: }
1262:
1263: public int[] getClassMethodCount() {
1264: return classMethodCount;
1265: }
1266:
1267: public String[] getClassSuper() {
1268: return classSuper;
1269: }
1270:
1271: public String[] getClassThis() {
1272: return classThis;
1273: }
1274:
1275: public int[] getCodeMaxNALocals() {
1276: return codeMaxNALocals;
1277: }
1278:
1279: public int[] getCodeMaxStack() {
1280: return codeMaxStack;
1281: }
1282:
1283: public ArrayList[][] getFieldAttributes() {
1284: return fieldAttributes;
1285: }
1286:
1287: public String[][] getFieldDescr() {
1288: return fieldDescr;
1289: }
1290:
1291: public long[][] getFieldFlags() {
1292: return fieldFlags;
1293: }
1294:
1295: /**
1296: * Answer an ArrayList of ArrayLists which hold the the code attributes
1297: * corresponding to all classes in order.
1298: *
1299: * If a class doesn't have any attributes, the corresponding element in this
1300: * list will be an empty ArrayList.
1301: * @return ArrayList
1302: */
1303: public ArrayList getOrderedCodeAttributes() {
1304: ArrayList orderedAttributeList = new ArrayList();
1305: for (int classIndex = 0; classIndex < codeAttributes.length; classIndex++) {
1306: ArrayList currentAttributes = new ArrayList();
1307: for (int attributeIndex = 0; attributeIndex < codeAttributes[classIndex]
1308: .size(); attributeIndex++) {
1309: Attribute attribute = (Attribute) codeAttributes[classIndex]
1310: .get(attributeIndex);
1311: currentAttributes.add(attribute);
1312: }
1313: orderedAttributeList.add(currentAttributes);
1314: }
1315: return orderedAttributeList;
1316: }
1317:
1318: public ArrayList[][] getMethodAttributes() {
1319: return methodAttributes;
1320: }
1321:
1322: public String[][] getMethodDescr() {
1323: return methodDescr;
1324: }
1325:
1326: public long[][] getMethodFlags() {
1327: return methodFlags;
1328: }
1329:
1330: /**
1331: * Returns null if all classes should use the default major and minor
1332: * version or an array of integers containing the major version numberss to
1333: * use for each class in the segment
1334: *
1335: * @return Class file major version numbers, or null if none specified
1336: */
1337: public int[] getClassVersionMajor() {
1338: return classVersionMajor;
1339: }
1340:
1341: /**
1342: * Returns null if all classes should use the default major and minor
1343: * version or an array of integers containing the minor version numberss to
1344: * use for each class in the segment
1345: *
1346: * @return Class file minor version numbers, or null if none specified
1347: */
1348: public int[] getClassVersionMinor() {
1349: return classVersionMinor;
1350: }
1351:
1352: public int[] getCodeHandlerCount() {
1353: return codeHandlerCount;
1354: }
1355:
1356: public int[][] getCodeHandlerCatchPO() {
1357: return codeHandlerCatchPO;
1358: }
1359:
1360: public String[][] getCodeHandlerClassRCN() {
1361: return codeHandlerClassRCN;
1362: }
1363:
1364: public int[][] getCodeHandlerEndPO() {
1365: return codeHandlerEndPO;
1366: }
1367:
1368: public int[][] getCodeHandlerStartP() {
1369: return codeHandlerStartP;
1370: }
1371:
1372: public IcTuple[][] getIcLocal() {
1373: return icLocal;
1374: }
1375:
1376: }
|