    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 */
    017package org.apache.bcel.generic;
    018
    019import java.util.Objects;
    020
    021import org.apache.bcel.classfile.LineNumber;
    022
    023/**
    024 * This class represents a line number within a method, i.e., give an instruction a line number corresponding to the
    025 * source code line.
    026 *
    027 * @see LineNumber
    028 * @see MethodGen
    029 */
    030public class LineNumberGen implements InstructionTargeter, Cloneable {
    031
    032    static final LineNumberGen[] EMPTY_ARRAY = {};
    033
    034    private InstructionHandle ih;
    035    private int srcLine;
    036
    037    /**
    038     * Create a line number.
    039     *
    040     * @param ih instruction handle to reference
    041     */
    042    public LineNumberGen(final InstructionHandle ih, final int srcLine) {
    043        setInstruction(ih);
    044        setSourceLine(srcLine);
    045    }
    046
    047    @Override
    048    public Object clone() {
    049        try {
    050            return super.clone();
    051        } catch (final CloneNotSupportedException e) {
    052            throw new Error("Clone Not Supported"); // never happens
    053        }
    054    }
    055
    056    /**
    057     * @return true, if ih is target of this line number
    058     */
    059    @Override
    060    public boolean containsTarget(final InstructionHandle ih) {
    061        return this.ih == ih;
    062    }
    063
    064    public InstructionHandle getInstruction() {
    065        return ih;
    066    }
    067
    068    /**
    069     * Get LineNumber attribute.
    070     *
    071     * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods
    072     * has been called for the instruction list.
    073     */
    074    public LineNumber getLineNumber() {
    075        return new LineNumber(ih.getPosition(), srcLine);
    076    }
    077
    078    public int getSourceLine() {
    079        return srcLine;
    080    }
    081
    082    public void setInstruction(final InstructionHandle instructionHandle) { // TODO could be package-protected?
    083        Objects.requireNonNull(instructionHandle, "instructionHandle");
    084        BranchInstruction.notifyTarget(this.ih, instructionHandle, this);
    085        this.ih = instructionHandle;
    086    }
    087
    088    public void setSourceLine(final int srcLine) { // TODO could be package-protected?
    089        this.srcLine = srcLine;
    090    }
    091
    092    /**
    093     * @param oldIh old target
    094     * @param newIh new target
    095     */
    096    @Override
    097    public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) {
    098        if (oldIh != ih) {
    099            throw new ClassGenException("Not targeting " + oldIh + ", but " + ih + "}");
    100        }
    101        setInstruction(newIh);
    102    }
    103}