    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 *   https://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019package org.apache.commons.compress.harmony.unpack200.bytecode;
    020
    021import java.io.DataOutputStream;
    022import java.io.IOException;
    023import java.util.Arrays;
    024import java.util.List;
    025
    026import org.apache.commons.compress.harmony.pack200.Pack200Exception;
    027
    028/**
    029 * Abstract superclass for attributes that have some part encoded with Byte Code Injection (BCI) renumbering.
    030 */
    031public abstract class BCIRenumberedAttribute extends Attribute {
    032
    033    /**
    034     * Whether renumbering has occurred.
    035     */
    036    protected boolean renumbered;
    037
    038    /**
    039     * Constructs a new instance for an attribute name.
    040     *
    041     * @param attributeName an attribute name.
    042     */
    043    public BCIRenumberedAttribute(final CPUTF8 attributeName) {
    044        super(attributeName);
    045    }
    046
    047    @Override
    048    protected abstract int getLength();
    049
    050    /**
    051     * Gets the array of indices for the start of line numbers.
    052     *
    053     * @return the array of indices for the start of line numbers.
    054     */
    055    protected abstract int[] getStartPCs();
    056
    057    /*
    058     * (non-Javadoc)
    059     *
    060     * @see org.apache.commons.compress.harmony.unpack200.bytecode.Attribute#hasBCIRenumbering()
    061     */
    062    @Override
    063    public boolean hasBCIRenumbering() {
    064        return true;
    065    }
    066
    067    /**
    068     * In Pack200, line number tables are BCI renumbered. This method takes the byteCodeOffsets (which is a List of Integers specifying the offset in the byte
    069     * code array of each instruction) and updates the start_pcs so that it points to the instruction index itself, not the BCI renumbering of the instruction.
    070     *
    071     * @param byteCodeOffsets List of Integer offsets of the byte code array.
    072     * @throws Pack200Exception Thrown from a subclass.
    073     */
    074    public void renumber(final List<Integer> byteCodeOffsets) throws Pack200Exception {
    075        if (renumbered) {
    076            throw new Error("Trying to renumber a line number table that has already been renumbered");
    077        }
    078        renumbered = true;
    079        final int[] startPCs = getStartPCs();
    080        Arrays.setAll(startPCs, i -> byteCodeOffsets.get(startPCs[i]).intValue());
    081    }
    082
    083    @Override
    084    public abstract String toString();
    085
    086    @Override
    087    protected abstract void writeBody(DataOutputStream dos) throws IOException;
    088
    089}