View Javadoc
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 }