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 * @return target of instruction. 058 */ 059 public InstructionHandle getTarget() { 060 return bi.getTarget(); 061 } 062 063 /** 064 * Sets new contents. Old instruction is disposed and may not be used anymore. 065 */ 066 @Override // This is only done in order to apply the additional type check; could be merged with super impl. 067 public void setInstruction(final Instruction i) { // TODO could be package-protected? 068 super.setInstruction(i); 069 if (!(i instanceof BranchInstruction)) { 070 throw new ClassGenException("Assigning " + i + " to branch handle which is not a branch instruction"); 071 } 072 bi = (BranchInstruction) i; 073 } 074 075 @Override 076 void setPosition(final int pos) { 077 // Original code: i_position = bi.position = pos; 078 bi.setPosition(pos); 079 super.setPosition(pos); 080 } 081 082 /** 083 * Pass new target to instruction. 084 */ 085 public void setTarget(final InstructionHandle ih) { 086 bi.setTarget(ih); 087 } 088 089 @Override 090 protected int updatePosition(final int offset, final int maxOffset) { 091 final int x = bi.updatePosition(offset, maxOffset); 092 super.setPosition(bi.getPosition()); 093 return x; 094 } 095 096 /** 097 * Update target of instruction. 098 */ 099 public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) { 100 bi.updateTarget(oldIh, newIh); 101 } 102}