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.bcel.generic;
20
21 /**
22 * BranchHandle is returned by specialized InstructionList.append() whenever a BranchInstruction is appended. This is
23 * useful when the target of this instruction is not known at time of creation and must be set later via setTarget().
24 *
25 * @see InstructionHandle
26 * @see Instruction
27 * @see InstructionList
28 */
29 public final class BranchHandle extends InstructionHandle {
30
31 /**
32 * Factory method.
33 */
34 static BranchHandle getBranchHandle(final BranchInstruction i) {
35 return new BranchHandle(i);
36 }
37
38 // This is also a cache in case the InstructionHandle#swapInstruction() method is used
39 // See BCEL-273
40 private BranchInstruction bi; // An alias in fact, but saves lots of casts
41
42 private BranchHandle(final BranchInstruction i) {
43 super(i);
44 bi = i;
45 }
46
47 /*
48 * Override InstructionHandle methods: delegate to branch instruction. Through this overriding all access to the private
49 * i_position field should be prevented.
50 */
51 @Override
52 public int getPosition() {
53 return bi.getPosition();
54 }
55
56 /**
57 * @return target of instruction.
58 */
59 public InstructionHandle getTarget() {
60 return bi.getTarget();
61 }
62
63 /**
64 * Sets new contents. Old instruction is disposed and may not be used anymore.
65 */
66 @Override // This is only done in order to apply the additional type check; could be merged with super impl.
67 public void setInstruction(final Instruction i) { // TODO could be package-protected?
68 super.setInstruction(i);
69 if (!(i instanceof BranchInstruction)) {
70 throw new ClassGenException("Assigning " + i + " to branch handle which is not a branch instruction");
71 }
72 bi = (BranchInstruction) i;
73 }
74
75 @Override
76 void setPosition(final int pos) {
77 // Original code: i_position = bi.position = pos;
78 bi.setPosition(pos);
79 super.setPosition(pos);
80 }
81
82 /**
83 * Pass new target to instruction.
84 */
85 public void setTarget(final InstructionHandle ih) {
86 bi.setTarget(ih);
87 }
88
89 @Override
90 protected int updatePosition(final int offset, final int maxOffset) {
91 final int x = bi.updatePosition(offset, maxOffset);
92 super.setPosition(bi.getPosition());
93 return x;
94 }
95
96 /**
97 * Update target of instruction.
98 */
99 public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) {
100 bi.updateTarget(oldIh, newIh);
101 }
102 }