001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.generic; 020 021/** 022 * BranchHandle is returned by specialized InstructionList.append() whenever a BranchInstruction is appended. This is 023 * useful when the target of this instruction is not known at time of creation and must be set later via setTarget(). 024 * 025 * @see InstructionHandle 026 * @see Instruction 027 * @see InstructionList 028 */ 029public final class BranchHandle extends InstructionHandle { 030 031 /** 032 * Factory method. 033 */ 034 static BranchHandle getBranchHandle(final BranchInstruction i) { 035 return new BranchHandle(i); 036 } 037 038 // This is also a cache in case the InstructionHandle#swapInstruction() method is used 039 // See BCEL-273 040 private BranchInstruction bi; // An alias in fact, but saves lots of casts 041 042 private BranchHandle(final BranchInstruction i) { 043 super(i); 044 bi = i; 045 } 046 047 /* 048 * Override InstructionHandle methods: delegate to branch instruction. Through this overriding all access to the private 049 * i_position field should be prevented. 050 */ 051 @Override 052 public int getPosition() { 053 return bi.getPosition(); 054 } 055 056 /** 057 * Gets the target of instruction. 058 * 059 * @return target of instruction. 060 */ 061 public InstructionHandle getTarget() { 062 return bi.getTarget(); 063 } 064 065 /** 066 * Sets new contents. Old instruction is disposed and may not be used anymore. 067 */ 068 @Override // This is only done in order to apply the additional type check; could be merged with super impl. 069 public void setInstruction(final Instruction i) { // TODO could be package-protected? 070 super.setInstruction(i); 071 if (!(i instanceof BranchInstruction)) { 072 throw new ClassGenException("Assigning " + i + " to branch handle which is not a branch instruction"); 073 } 074 bi = (BranchInstruction) i; 075 } 076 077 @Override 078 void setPosition(final int pos) { 079 // Original code: i_position = bi.position = pos; 080 bi.setPosition(pos); 081 super.setPosition(pos); 082 } 083 084 /** 085 * Pass new target to instruction. 086 * 087 * @param ih the new target. 088 */ 089 public void setTarget(final InstructionHandle ih) { 090 bi.setTarget(ih); 091 } 092 093 @Override 094 protected int updatePosition(final int offset, final int maxOffset) { 095 final int x = bi.updatePosition(offset, maxOffset); 096 super.setPosition(bi.getPosition()); 097 return x; 098 } 099 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}