View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   *
17   */
18  package org.apache.bcel.generic;
19  
20  /**
21   * BranchHandle is returned by specialized InstructionList.append() whenever a
22   * BranchInstruction is appended. This is useful when the target of this
23   * instruction is not known at time of creation and must be set later
24   * via setTarget().
25   *
26   * @see InstructionHandle
27   * @see Instruction
28   * @see InstructionList
29   * @version $Id: BranchHandle.html 1018313 2017-09-18 09:03:04Z britter $
30   */
31  public final class BranchHandle extends InstructionHandle {
32  
33      // This is also a cache in case the InstructionHandle#swapInstruction() method is used
34      // See BCEL-273
35      private BranchInstruction bi; // An alias in fact, but saves lots of casts
36  
37  
38      private BranchHandle(final BranchInstruction i) {
39          super(i);
40          bi = i;
41      }
42  
43      /** Factory methods.
44       */
45      private static BranchHandle bh_list = null; // List of reusable handles
46  
47  
48      static BranchHandle getBranchHandle( final BranchInstruction i ) {
49          if (bh_list == null) {
50              return new BranchHandle(i);
51          }
52          final BranchHandle bh = bh_list;
53          bh_list = (BranchHandle) bh.getNext();
54          bh.setInstruction(i);
55          return bh;
56      }
57  
58  
59      /** Handle adds itself to the list of resuable handles.
60       */
61      @Override
62      protected void addHandle() {
63          super.setNext(bh_list);
64          bh_list = this;
65      }
66  
67  
68      /* Override InstructionHandle methods: delegate to branch instruction.
69       * Through this overriding all access to the private i_position field should
70       * be prevented.
71       */
72      @Override
73      public int getPosition() {
74          return bi.getPosition();
75      }
76  
77  
78      @Override
79      void setPosition( final int pos ) {
80          // Original code: i_position = bi.position = pos;
81          bi.setPosition(pos);
82          super.setPosition(pos);
83      }
84  
85  
86      @Override
87      protected int updatePosition( final int offset, final int max_offset ) {
88          final int x = bi.updatePosition(offset, max_offset);
89          super.setPosition(bi.getPosition());
90          return x;
91      }
92  
93  
94      /**
95       * Pass new target to instruction.
96       */
97      public void setTarget( final InstructionHandle ih ) {
98          bi.setTarget(ih);
99      }
100 
101 
102     /**
103      * Update target of instruction.
104      */
105     public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) {
106         bi.updateTarget(old_ih, new_ih);
107     }
108 
109 
110     /**
111      * @return target of instruction.
112      */
113     public InstructionHandle getTarget() {
114         return bi.getTarget();
115     }
116 
117 
118     /**
119      * Set new contents. Old instruction is disposed and may not be used anymore.
120      */
121     @Override // This is only done in order to apply the additional type check; could be merged with super impl.
122     public void setInstruction( final Instruction i ) { // TODO could be package-protected?
123         super.setInstruction(i);
124         if (!(i instanceof BranchInstruction)) {
125             throw new ClassGenException("Assigning " + i
126                     + " to branch handle which is not a branch instruction");
127         }
128         bi = (BranchInstruction) i;
129     }
130 }