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