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       * 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 }