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 * Gets the target of instruction.
58 *
59 * @return target of instruction.
60 */
61 public InstructionHandle getTarget() {
62 return bi.getTarget();
63 }
64
65 /**
66 * Sets new contents. Old instruction is disposed and may not be used anymore.
67 */
68 @Override // This is only done in order to apply the additional type check; could be merged with super impl.
69 public void setInstruction(final Instruction i) { // TODO could be package-protected?
70 super.setInstruction(i);
71 if (!(i instanceof BranchInstruction)) {
72 throw new ClassGenException("Assigning " + i + " to branch handle which is not a branch instruction");
73 }
74 bi = (BranchInstruction) i;
75 }
76
77 @Override
78 void setPosition(final int pos) {
79 // Original code: i_position = bi.position = pos;
80 bi.setPosition(pos);
81 super.setPosition(pos);
82 }
83
84 /**
85 * Pass new target to instruction.
86 *
87 * @param ih the new target.
88 */
89 public void setTarget(final InstructionHandle ih) {
90 bi.setTarget(ih);
91 }
92
93 @Override
94 protected int updatePosition(final int offset, final int maxOffset) {
95 final int x = bi.updatePosition(offset, maxOffset);
96 super.setPosition(bi.getPosition());
97 return x;
98 }
99
100 /**
101 * Update target of instruction.
102 *
103 * @param oldIh the old instruction handle.
104 * @param newIh the new instruction handle.
105 */
106 public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) {
107 bi.updateTarget(oldIh, newIh);
108 }
109 }