public void unpack()

in src/main/java/org/apache/commons/compress/harmony/unpack200/BcBands.java [428:528]


    public void unpack() throws Pack200Exception {
        final int classCount = header.getClassCount();
        final long[][] methodFlags = segment.getClassBands().getMethodFlags();
        final int[] codeMaxNALocals = segment.getClassBands().getCodeMaxNALocals();
        final int[] codeMaxStack = segment.getClassBands().getCodeMaxStack();
        final ArrayList<Attribute>[][] methodAttributes = segment.getClassBands().getMethodAttributes();
        final String[][] methodDescr = segment.getClassBands().getMethodDescr();

        final AttributeLayoutMap attributeDefinitionMap = segment.getAttrDefinitionBands().getAttributeDefinitionMap();

        final AttributeLayout abstractModifier = attributeDefinitionMap.getAttributeLayout(AttributeLayout.ACC_ABSTRACT, AttributeLayout.CONTEXT_METHOD);
        final AttributeLayout nativeModifier = attributeDefinitionMap.getAttributeLayout(AttributeLayout.ACC_NATIVE, AttributeLayout.CONTEXT_METHOD);
        final AttributeLayout staticModifier = attributeDefinitionMap.getAttributeLayout(AttributeLayout.ACC_STATIC, AttributeLayout.CONTEXT_METHOD);

        final int[] wideByteCodeArray = new int[wideByteCodes.size()];
        for (int index = 0; index < wideByteCodeArray.length; index++) {
            wideByteCodeArray[index] = wideByteCodes.get(index).intValue();
        }
        final OperandManager operandManager = new OperandManager(bcCaseCount, bcCaseValue, bcByte, bcShort, bcLocal, bcLabel, bcIntRef, bcFloatRef, bcLongRef,
                bcDoubleRef, bcStringRef, bcClassRef, bcFieldRef, bcMethodRef, bcIMethodRef, bcThisField, bcSuperField, bcThisMethod, bcSuperMethod, bcInitRef,
                wideByteCodeArray);
        operandManager.setSegment(segment);

        int i = 0;
        final ArrayList<List<Attribute>> orderedCodeAttributes = segment.getClassBands().getOrderedCodeAttributes();
        int codeAttributeIndex = 0;

        // Exception table fields
        final int[] handlerCount = segment.getClassBands().getCodeHandlerCount();
        final int[][] handlerStartPCs = segment.getClassBands().getCodeHandlerStartP();
        final int[][] handlerEndPCs = segment.getClassBands().getCodeHandlerEndPO();
        final int[][] handlerCatchPCs = segment.getClassBands().getCodeHandlerCatchPO();
        final int[][] handlerClassTypes = segment.getClassBands().getCodeHandlerClassRCN();

        final boolean allCodeHasFlags = segment.getSegmentHeader().getOptions().hasAllCodeFlags();
        final boolean[] codeHasFlags = segment.getClassBands().getCodeHasAttributes();

        for (int c = 0; c < classCount; c++) {
            final int numberOfMethods = methodFlags[c].length;
            for (int m = 0; m < numberOfMethods; m++) {
                final long methodFlag = methodFlags[c][m];
                if (!abstractModifier.matches(methodFlag) && !nativeModifier.matches(methodFlag)) {
                    final int maxStack = codeMaxStack[i];
                    int maxLocal = codeMaxNALocals[i];
                    if (!staticModifier.matches(methodFlag)) {
                        maxLocal++; // one for 'this' parameter
                    }
                    // I believe this has to take wide arguments into account
                    maxLocal += SegmentUtils.countInvokeInterfaceArgs(methodDescr[c][m]);
                    final String[] cpClass = segment.getCpBands().getCpClass();
                    operandManager.setCurrentClass(cpClass[segment.getClassBands().getClassThisInts()[c]]);
                    operandManager.setSuperClass(cpClass[segment.getClassBands().getClassSuperInts()[c]]);
                    final List<ExceptionTableEntry> exceptionTable = new ArrayList<>();
                    if (handlerCount != null) {
                        for (int j = 0; j < handlerCount[i]; j++) {
                            final int handlerClass = handlerClassTypes[i][j] - 1;
                            CPClass cpHandlerClass = null;
                            if (handlerClass != -1) {
                                // The handlerClass will be null if the
                                // catch is a finally (that is, the
                                // exception table catch_type should be 0
                                cpHandlerClass = segment.getCpBands().cpClassValue(handlerClass);
                            }
                            final ExceptionTableEntry entry = new ExceptionTableEntry(handlerStartPCs[i][j], handlerEndPCs[i][j], handlerCatchPCs[i][j],
                                    cpHandlerClass);
                            exceptionTable.add(entry);
                        }
                    }
                    final CodeAttribute codeAttr = new CodeAttribute(maxStack, maxLocal, methodByteCodePacked[c][m], segment, operandManager, exceptionTable);
                    final List<Attribute> methodAttributesList = methodAttributes[c][m];
                    // Make sure we add the code attribute in the right place
                    int indexForCodeAttr = 0;
                    for (final Attribute attribute : methodAttributesList) {
                        if (!(attribute instanceof NewAttribute) || ((NewAttribute) attribute).getLayoutIndex() >= 15) {
                            break;
                        }
                        indexForCodeAttr++;
                    }
                    methodAttributesList.add(indexForCodeAttr, codeAttr);
                    codeAttr.renumber(codeAttr.byteCodeOffsets);
                    final List<Attribute> currentAttributes;
                    if (allCodeHasFlags) {
                        currentAttributes = orderedCodeAttributes.get(i);
                    } else if (codeHasFlags[i]) {
                        currentAttributes = orderedCodeAttributes.get(codeAttributeIndex);
                        codeAttributeIndex++;
                    } else {
                        currentAttributes = Collections.EMPTY_LIST;
                    }
                    for (final Attribute currentAttribute : currentAttributes) {
                        codeAttr.addAttribute(currentAttribute);
                        // Fix up the line numbers if needed
                        if (currentAttribute.hasBCIRenumbering()) {
                            ((BCIRenumberedAttribute) currentAttribute).renumber(codeAttr.byteCodeOffsets);
                        }
                    }
                    i++;
                }
            }
        }
    }