1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.commons.compress.harmony.unpack200.bytecode;
20
21 import java.io.DataOutputStream;
22 import java.io.IOException;
23 import java.util.Arrays;
24 import java.util.List;
25
26 import org.apache.commons.compress.harmony.pack200.Pack200Exception;
27
28 /**
29 * Abstract superclass for attributes that have some part encoded with Byte Code Injection (BCI) renumbering.
30 */
31 public abstract class BCIRenumberedAttribute extends Attribute {
32
33 /**
34 * Whether renumbering has occurred.
35 */
36 protected boolean renumbered;
37
38 /**
39 * Constructs a new instance for an attribute name.
40 *
41 * @param attributeName an attribute name.
42 */
43 public BCIRenumberedAttribute(final CPUTF8 attributeName) {
44 super(attributeName);
45 }
46
47 @Override
48 protected abstract int getLength();
49
50 /**
51 * Gets the array of indices for the start of line numbers.
52 *
53 * @return the array of indices for the start of line numbers.
54 */
55 protected abstract int[] getStartPCs();
56
57 /*
58 * (non-Javadoc)
59 *
60 * @see org.apache.commons.compress.harmony.unpack200.bytecode.Attribute#hasBCIRenumbering()
61 */
62 @Override
63 public boolean hasBCIRenumbering() {
64 return true;
65 }
66
67 /**
68 * 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
69 * 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.
70 *
71 * @param byteCodeOffsets List of Integer offsets of the byte code array.
72 * @throws Pack200Exception Thrown from a subclass.
73 */
74 public void renumber(final List<Integer> byteCodeOffsets) throws Pack200Exception {
75 if (renumbered) {
76 throw new Error("Trying to renumber a line number table that has already been renumbered");
77 }
78 renumbered = true;
79 final int[] startPCs = getStartPCs();
80 Arrays.setAll(startPCs, i -> byteCodeOffsets.get(startPCs[i]).intValue());
81 }
82
83 @Override
84 public abstract String toString();
85
86 @Override
87 protected abstract void writeBody(DataOutputStream dos) throws IOException;
88
89 }