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 * @version $Id: BranchHandle.java 1749603 2016-06-21 20:50:19Z ggregory $
030 */
031public final class BranchHandle extends InstructionHandle {
032
033    // This is also a cache in case the InstructionHandle#swapInstruction() method is used
034    // See BCEL-273
035    private BranchInstruction bi; // An alias in fact, but saves lots of casts
036
037
038    private BranchHandle(final BranchInstruction i) {
039        super(i);
040        bi = i;
041    }
042
043    /** Factory methods.
044     */
045    private static BranchHandle bh_list = null; // List of reusable handles
046
047
048    static BranchHandle getBranchHandle( final BranchInstruction i ) {
049        if (bh_list == null) {
050            return new BranchHandle(i);
051        }
052        final BranchHandle bh = bh_list;
053        bh_list = (BranchHandle) bh.getNext();
054        bh.setInstruction(i);
055        return bh;
056    }
057
058
059    /** Handle adds itself to the list of resuable handles.
060     */
061    @Override
062    protected void addHandle() {
063        super.setNext(bh_list);
064        bh_list = this;
065    }
066
067
068    /* Override InstructionHandle methods: delegate to branch instruction.
069     * Through this overriding all access to the private i_position field should
070     * be prevented.
071     */
072    @Override
073    public int getPosition() {
074        return bi.getPosition();
075    }
076
077
078    @Override
079    void setPosition( final int pos ) {
080        // Original code: i_position = bi.position = pos;
081        bi.setPosition(pos);
082        super.setPosition(pos);
083    }
084
085
086    @Override
087    protected int updatePosition( final int offset, final int max_offset ) {
088        final int x = bi.updatePosition(offset, max_offset);
089        super.setPosition(bi.getPosition());
090        return x;
091    }
092
093
094    /**
095     * Pass new target to instruction.
096     */
097    public void setTarget( final InstructionHandle ih ) {
098        bi.setTarget(ih);
099    }
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}